ContentPresenter вместо UserControl добавлен в мою настраиваемую панель

Я создал пользовательскую панель, унаследованную от Canvas. Я хотел бы использовать его для просмотра моих пользовательских элементов управления в ItemsControl.

Это мой XAML:

<ItemsControl ItemsSource="{Binding Groups}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <c:MyCustomPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <ItemContainerTemplate>
                <app:MyUserControl Margin="5" MinWidth="200"/>                    
            </ItemContainerTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

Как видите, в моем пользовательском элементе управления MinWidth установлено на 200.

Теперь в моей пользовательской панели есть переопределенный метод ArrangeOverride:

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        foreach (UIElement obj in InternalChildren)
        {
           //some other code   
        }
        return arrangeSize;
    }

Проблема в том, что по какой-то причине InternalChildren состоит из элементов ContentPresenter, а не из моих пользовательских элементов управления. Конечно, в каждом ContentPresenter есть мой пользовательский контроль, но это не то, чем я хотел бы быть. Мне нужно прочитать здесь MinWidth моего userControl, но вместо этого я читаю его из ContentPresenter (который всегда равен 0).

Когда я делаю очень простой тест:

<ItemsControl ItemsSource="{Binding Buttons}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <c:MyCustomPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

где Buttons — это просто список элементов управления Button, все работает как положено. Поэтому я думаю, что проблема может быть где-то в том, как я использую ItemsControl. Но понятия не имею, как его отремонтировать.

ItemsControl оборачивает все предметы в ContentPresenter.

mm8 22.05.2019 16:38

Так почему же в примере с кнопками я получаю кнопки вместо CP?

Adam Jachocki 22.05.2019 16:40

Потому что не создано ContentPresenter и не применено ItemTemplate для UIElements, как Buttons.

mm8 22.05.2019 16:41

Чтобы быть точным, в ContentPresenter помещаются только те элементы, которые не являются UIElement. Таким образом, если вы назначаете коллекцию кнопок свойству ItemsSource, они не упаковываются, а вместо этого напрямую добавляются в ItemsPanel.

Clemens 22.05.2019 16:41

Единственный способ добавить MyUserControl в качестве прямого потомка MyCustomPanel — это создать производный ItemsControl и переопределить методы GetContainerForItemOverride и IsItemItsOwnContainerOverride.

Clemens 22.05.2019 16:48

Я вижу сейчас. Спасибо за помощь.

Adam Jachocki 22.05.2019 16:57
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
6
102
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Установите свойство MinWidth ContentPresenter в ItemContainerStyle:

<ItemsControl ItemsSource="{Binding Groups}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <c:MyCustomPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <app:MyUserControl Margin="5"/>                    
        </DataTemplate>
    </ItemsControl.ItemTemplate>

    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="MinWidth" Value="200"/>                    
        </Style >
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

The problem is that for some reason InternalChildren consist of ContentPresenter items instead of my user controls.

Это потому, что ItemsControl оборачивает все элементы в ContentPresenter, если они не являются UIElements. Если вы привязываетесь к коллекции UIElements, например, Buttons, ContentPresenter не создается, но и не применяется ItemTemplate.

Вы можете либо установить MinWidth контейнеров ContentPresenter, как это было предложено @Clemens, либо предотвратить создание ContentPresenters, внедрив свои собственные ItemsControl и переопределив методы GetContainerForItemOverride() и IsItemItsOwnContainerOverride():

public class MyItemsControl : System.Windows.Controls.ItemsControl
{
    protected virtual DependencyObject GetContainerForItemOverride()
    {
        return new MyUserControl();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is MyUserControl);
    }
}

Другие вопросы по теме