Andrew Stephens
Andrew Stephens

Reputation: 10203

Can't use ItemTemplate and ItemContainerStyle together?

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?

Upvotes: 5

Views: 4317

Answers (2)

Indy Singh
Indy Singh

Reputation: 37

I ran into the same problem using code snippets from stackoverflow. The problem can be fixed if you let visual studio generate the default ItemContainerStyle. It is quite a long template so I just delete the parts I didn't need.

In visual studio click on the ListView in designer, in the properties windows scroll down to the miscellaneous section, then click on the down-arrow next to ItemContainerStyle, then click on convert to a new resource.

WARNING there are two very similar items on the list (ItemContainerStyle and ItemContainerStyleSelector) pick the right one. It is easy to miss if the properties window is not wide enough.

Upvotes: 0

Sheridan
Sheridan

Reputation: 69979

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>

Upvotes: 5

Related Questions