Укажите ControlTemplate для ItemsControl.ItemContainerStyle - PullRequest
19 голосов
/ 22 августа 2010

Следующее похоже на то, что я пытаюсь выполнить.Однако я получаю сообщение об ошибке

Неверное значение PropertyDescriptor.

в шаблоне Setter.Я подозреваю, что это потому, что я не указал TargetType для Style;однако, я не знаю тип контейнера для ItemsControl.

<ItemsControl>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel>
                            <TextBlock Text="Some Content Here" />
                            <ContentPresenter />
                            <Button Content="Edit" />
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <!-- heterogenous controls -->
    <ItemsControl.Items> 
        <Button Content="Content 1" />
        <TextBox Text="Content 2" />
        <Label Content="Content 3" />
    </ItemsControl.Items>
</ItemsControl>

Ответы [ 2 ]

39 голосов
/ 22 августа 2010

В качестве имени свойства можно указать имя типа:

<Setter Property="Control.Template">

Контейнером для ItemsControl обычно является ContentPresenter, но если дочерним элементом является UIElement, он не будет использовать контейнер. В этом случае все дочерние элементы являются элементами управления, поэтому ItemContainerStyle будет применяться к ним напрямую. Если вы добавите элемент, отличный от UIElement, этот установщик установит свойство Control.Template для ContentPresenter, что будет успешным, но не даст никакого эффекта.

На самом деле, звучит так, будто вы хотите заключить каждого ребенка в контейнер, даже если он уже UIElement. Для этого вам нужно будет использовать подкласс ItemsControl. Вы можете использовать существующий, например ListBox, или подкласс ItemsControl и переопределить GetContainerForItemOverride и IsItemItsOwnContainerOverride, чтобы обернуть элементы в своем собственном контейнере. Вы можете обернуть их в ContentControl, а затем использовать это как TargetType для Style.

public class CustomItemsControl
    : ItemsControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ContentControl();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        // Even wrap other ContentControls
        return false;
    }
}

Вам также нужно установить TargetType на ControlTemplate, чтобы ContentPresenter связывался со свойством Content:

<ControlTemplate TargetType="ContentControl">
2 голосов
/ 19 сентября 2011

Также, если вы хотите сделать все это только с XAML, вы можете просто использовать ListBox вместо ItemsControl и определить стиль для ListBoxItem:

        <ListBox ItemsSource="{Binding Elements.ListViewModels}">
        <ListBox.Resources>
            <Style TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <StackPanel>
                                <TextBlock>Some Content Here</TextBlock>
                                <ContentPresenter Content="{TemplateBinding Content}" />
                                <Button>Edit</Button>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

Обратите внимание, что, поскольку я использую ListBox, контейнером является ListBoxItem.(Обычно контейнер для элемента управления списком WPF по умолчанию всегда называется Item), поэтому мы создаем стиль для ListBoxItem:

<Style TargetType="ListBoxItem">

Затем создаем новый ControlTemplate для ListBoxItem.Обратите внимание, что ContentPresenter не используется, как это всегда появляется в статьях и руководствах, вам необходимо привязать шаблон к свойству Content объекта ListBoxItem, чтобы он отображал содержимое этого элемента.

<ContentPresenter Content="{TemplateBinding Content}" />

Я простобыла такая же проблема и исправлена ​​таким образом.Мне не нужны некоторые функции ListBox (выбор элементов), и с помощью этой техники выбор элементов больше не работает.

...