WPF: Alternating colors on a ItemsControl?
Asked Answered
H

3

44

How do I get alternating colors on a ItemsControl? I have AlternationCount set to 2, but the ItemsControl.AlternationIndex property always returns 0.

        <ItemsControl ItemsSource="{Binding}" AlternationCount="2">
            <ItemsControl.Resources>
                <Style x:Key="FooBar" TargetType="Grid">
                    <Style.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                            <Setter Property="Background" Value="Blue"/>
                        </Trigger>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                            <Setter Property="Background" Value="Red"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ItemsControl.Resources>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="0,0,0,10" Style="{StaticResource FooBar}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="25" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions >
                            <RowDefinition Height="Auto" />
                            <!--<RowDefinition Height="Auto" />-->
                        </Grid.RowDefinitions>

                        <CheckBox IsChecked="{Binding Checked, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
                        <Label Grid.Column="1" Content="{Binding CompanyName}" />
                        <Label Grid.Column="2" Content="{Binding TradeKey}" />
                        <Label Grid.Column="3" Content="{Binding TradeDate}" ContentStringFormat="d" />
                        <Label Grid.Column="4" Content="{Binding Cusip}" />
                        <Label Grid.Column="5" Content="{Binding IssueName}" />
                        <Label Grid.Column="6" Content="{Binding TotalUnits}" ContentStringFormat="N0" />

                        <!--<Expander Grid.Row="0" Grid.Column="7" Grid.ColumnSpan="7" IsExpanded="True">
                            <Expander.Header>
                                <StackPanel Orientation="Horizontal">
                                    <Label Content="Allocations"/>
                                    <Button Content="Edit" Name="cmdEdit" Click="cmdEdit_Click"  />
                                </StackPanel>
                            </Expander.Header>-->
                        <DataGrid Grid.Column="7" IsReadOnly="True" ItemsSource="{Binding Territories}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False">
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="Rep on Ticket" Binding="{Binding TradeCustomer.RepNameNotes}" />
                                <DataGridTextColumn Header="Rep # on Ticket" Binding="{Binding TradeCustomer.RepNumberNotes}" />
                                <DataGridTextColumn Header="State" Binding="{Binding TradeCustomer.AccountStateKey}" />
                                <DataGridTextColumn Header="Qty. on Ticket" Binding="{Binding TradeCustomer.Quantity, StringFormat=N0}" />

                                <DataGridTextColumn Header="Zip Code" Binding="{Binding ZipCode}" />
                                <DataGridTextColumn Header="State" Binding="{Binding State}" />
                                <DataGridTextColumn Header="Territory" Binding="{Binding Territory}" />

                            </DataGrid.Columns>

                        </DataGrid>
                        <!--</Expander>-->

                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.Template>
                <ControlTemplate>
                    <Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
                        <ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
        </ItemsControl>
Hesketh answered 10/12, 2010 at 0:23 Comment(1)
Check my answer on #3568278Wehrle
C
81

Check here http://www.codeproject.com/Articles/35886/WPF-ItemsControl-with-alternating-items-and-hover-.aspx

You have to change your code like this to get it working

    <ItemsControl ItemsSource="{Binding DataList}" AlternationCount="2">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="FooBar" Margin="0,0,0,10">                    
                   ----------------------------
                   ----------------------------
                </Grid>
                <DataTemplate.Triggers>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                        <Setter Property="Background" Value="Blue" TargetName="FooBar"/>
                    </Trigger>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                        <Setter Property="Background" Value="Red" TargetName="FooBar"/>
                    </Trigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
Chariot answered 10/12, 2010 at 4:27 Comment(4)
Ah, I see the difference now. Thanks.Hesketh
Just wanted to call out for this to work the ItemsControl.AlternationCount must also be set to 2 -- tripped me up for a few minutesIsraelitish
At first this did not work for me, but then I spotted the use of the Property AlternationCount which of course must be set to an integer above one to see any alternation at all. Thanks biju for this great sample.Cerda
If you want to use this for a TreeView you need to copy the Triggers into TreeView.ItemContainerStyle. Otherwise it didn't work for me.Almallah
W
12

Here is an alternative which may be a bit more general

<DataTemplate x:Key="AlternatingTemplate">
    <Border>
        <Border.Style>
            <Style TargetType="{x:Type Border}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), 
                                                   RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" 
                                 Value="0">
                        <Setter Property="Background" Value="White" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), 
                                                   RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" 
                                 Value="1">
                        <Setter Property="Background" Value="LightGray" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Border.Style>
        <ContentPresenter Content="{Binding}" />
    </Border>
</DataTemplate>

Usage:

<ItemsControl AlternationCount="2" 
              ItemTemplate="{StaticResource AlternatingTemplate}" 
              ItemsSource="{Binding SourceOfData}" />
When answered 7/1, 2016 at 15:14 Comment(0)
K
1

If you don't want to use the DataTemplate approach, you can create a custom control that uses a ContentControl as the item container, therefore allowing you to specify a background color.

Class:

public class ItemsControlAlternating : ItemsControl
{
    static ItemsControlAlternating()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating),
                 new FrameworkPropertyMetadata(typeof(ItemsControlAlternating)));
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ContentControl();
    }

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

Resource Dictionary:

<Style TargetType="{x:Type c:ItemsControlAlternating}">
   <Setter Property="AlternationCount" Value="2"/>
   <Setter Property="Template">
       <Setter.Value>
           <ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}">
               <ItemsPresenter/>
           </ControlTemplate>
       </Setter.Value>
   </Setter>
   <Setter Property="ItemContainerStyle">
       <Setter.Value>
           <Style TargetType="{x:Type ContentControl}">
               <Setter Property="Template">
                   <Setter.Value>
                       <ControlTemplate TargetType="{x:Type ContentControl}">
                           <Border Background="{TemplateBinding Background}">
                               <ContentPresenter/>
                           </Border>
                       </ControlTemplate>
                   </Setter.Value>
               </Setter>
               <Style.Triggers>
                   <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                       <Setter Property="Background" Value="Gray"/>
                   </Trigger>
                   <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                       <Setter Property="Background" Value="White"/>
                   </Trigger>
               </Style.Triggers>
           </Style>
       </Setter.Value>
   </Setter>
</Style>
Keloid answered 11/12, 2014 at 1:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.