I have seen some articles that show how to use AlternationIndex
with ListBox
es or ListView
s, but I had spent a few hours trying to get alternating background colors on the base ItemsControl
class and nothing seems to work. All ListBox
samples I saw use ListBoxItem
as the target type for the style that sets the background based onAlternationIndex
- like this one from MSDN:
<Grid>
<Grid.Resources>
<Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property="ListBox.AlternationIndex" Value="1">
<Setter Property="Background" Value="CornflowerBlue"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="ListBox.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Navy"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ListBox AlternationCount="3" ItemsSource="{StaticResource data}"
ItemContainerStyle="{StaticResource alternatingWithTriggers}">
</ListBox>
</Grid>
I want to use the ItemsControl
because I do not want the selection functionality and I think restyling a ListBox
to hide it might not be the best choice.
This is one of the things I was trying:
<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
<Grid>
<!-- some content here -->
</Grid>
</DataTemplate>
<!-- ... -->
<ItemsControl
ItemsSource="{Binding ObservableCollectionItems}"
AlternationCount="2"
>
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Grid.Background" Value="Red"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Grid.Background" Value="Blue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
The problem I saw was that the visual tree has a list of ContentPresenter
s that have ItemsControl.AlternationIndex
alternate between 0 and 1, but the Grid
in each ContentPresenter
has ItemsControl.AlternationIndex
set to 0.
There is probably something obvious I am missing...
hm .. After about 2 hours playing around, I finally found the solution that simply works:
I hope this answer helps others to save some time.
The ItemContainerStyle is applied to the elements generated by the ItemsControl: ContentPresenter. The ContentPresenter will in turn contain whatever you put in your ItemTemplate. In the case of a ListBox, the ItemContainerStyle is applied to the generated ListBoxItem.
The AlternationCount is, based on what you posted, only available on these generated items. You cannot use the ItemContainerStyle to set the Grid's background, because the Grid is unknown to that Style.
The following would be ideal, but unfortunately ContentPresenter has no background property. It would work for a ListBox (with ListBoxItems) however.
So you end up writing a style for the grid which binds to the AlternationIndex of your parent ContentPresenter.
Or, as I found on another post, and it works great for me... You can simply use a binding...
NB: remember to add AlterationCount="100" on your ItemsControl
I don't know how any of the prior answers are legit. I couldn't make any of them work (didn't try Jacobi's though). Anyways, I found the path to enlightenment here: http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, which lead me to adding the following in the xaml.cs code-behind:
and this in the xaml itself
This was so damn hard to find a working solution to that I'm actually angry
If you don't want to use the
DataTemplate
approach, you can create a custom control that uses aContentControl
as the item container, therefore allowing you to specify a background color.Class:
Resource Dictionary: