Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't use ItemTemplate and ItemContainerStyle together?

Tags:

wpf

I'm trying to apply both an ItemTemplate and ItemContainerStyle to an ItemsControl:-

<ItemsControl ItemsSource="{Binding LogEntries}"
              ItemTemplate="{StaticResource itemTemplate}"
              ItemContainerStyle="{StaticResource itemContainer}" />

However the ItemContainerStyle seems to be getting ignored (but it does work if I remove the ItemTemplate).

The item template is fairly complex and is used in a number of different views. In one specific view I need to change the spacing and background colour of the list items, hence why I was also trying to apply an ItemContainerStyle, which looks like this:-

<Style x:Key="itemContainer"
       TargetType="ContentPresenter">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Border x:Name="itemBorder"
                        Margin="4,0,4,4"
                        Background="#666666">
                    <ContentPresenter Content="{Binding}" />
                </Border>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

I'm a bit surprised that you can't apply both, unless I'm missing something? I assumed the ItemContainerStyle was really just a "wrapper" around the item content, regardless of whether or not the item's content is templated?

like image 480
Andrew Stephens Avatar asked Mar 11 '15 13:03

Andrew Stephens


1 Answers

The ItemContainerStyle is not a 'wrapper' for anything... it is a Style. You can set both the Style of the item container and the ItemTemplate property, but your problem is caused because you are trying to set the ContentTemplate property of the ContentPresenter in your Style and this is overwritten with the value of the ItemTemplate. (See @Clemens' link in the comments section).

One way to get around this is to use a ListBox that wraps its data items in ListBoxItems and to provide a value for the Template property instead of the ContentTemplate. (You can of course add a Style to remove it's borders to make it look like an ItemsControl). In this case, the ItemContainerStyle will affect the ListBoxItem instead. However, you must understand the difference.

The ItemContainerStyle will affect the ListBoxItem, whereas the ItemTemplate is used to define the data object inside. Therefore, it is appropriate to define a Border in the ItemContainerStyle and define how the data looks in the ItemTemplate. Try this:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Border Margin="4,0,4,4" Background="#666666">
                            <ContentPresenter Content="{Binding}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
like image 145
Sheridan Avatar answered Oct 29 '22 17:10

Sheridan