WPF 3.5 SP1 Feature: Alternating Rows

So what else is new in WPF 3.5 SP1? Here is a smaller but pretty nice feature for you ItemsControl fans: alternating rows.

This alternating row feature has been added in WPF 3.5 SP1 to make it easier to set properties like Background, Foreground, etc. on the rows of an ItemsControl in alternating fashion. Two new properties have been added to ItemsControl.

public class ItemsControl : Control, IAddChild, IGeneratorHost

{
public int AlternationCount { get; set; }

   public static readonly DependencyProperty AlternationCountProperty;

   public static readonly DependencyProperty AlternationIndexProperty;

   public static void SetAlternationIndex(DependencyObject element, int index){ }
}

 

AlternationCount is basically the count that the sequence will alternate on. It is set to the value 0 by default which means it is turned off. AlternationIndex is an attached property that gets set on each container item and will have a value in the range of [0, AlternationCount). Some examples may clarify its usage.

Here is a ListView that sets the AlternationCount to 2 and uses triggers for the AlternationIndex to change the background color.   

<Style x:Key="alternatingListViewItemStyle" TargetType="{x:Type ListViewItem}">

  <Style.Triggers>

      <Trigger Property="ItemsControl.AlternationIndex" Value="1">

          <Setter Property="Background" Value="LightBlue"></Setter>

      </Trigger>

      <Trigger Property="ItemsControl.AlternationIndex" Value="2">

          <Setter Property="Background" Value="LightGray"></Setter>

      </Trigger>

  </Style.Triggers>

</Style>   

<ListView ItemContainerStyle="{StaticResource alternatingListViewItemStyle}"

          AlternationCount="2" />

 

With the AlternationCount set to 2, the AlternationIndex can be set to 0 or 1. On every AlternationIndex set to 1, I’m going to set the background to blue.

 

 alternationCount

Notice that I also have a trigger when the AlternationIndex is set to 2, however, the current range for my AlternationIndex is [0, AlternationCount) so this trigger will not fire. If I do set the AlternationCount to 3, I will get something like this,

 

 alternationCount2

AlternationCount has also been added the HierarchicalDataTemplate and GroupStyle. Here are some examples of both. Oh, and you can also set properties with the AlternationIndex through a converter which I also have an example for below.

Here is the usage with a GroupStyle:             

<ListView.GroupStyle>

  <GroupStyle AlternationCount="2">

    <GroupStyle.HeaderTemplate>

        …

    </GroupStyle.HeaderTemplate>

    <GroupStyle.ContainerStyle>

      <Style TargetType="{x:Type GroupItem}">

        …

        <Style.Triggers>

          <Trigger Property="ItemsControl.AlternationIndex" Value="1">

           <Setter Property="Background" Value="LightBlue"></Setter>

          </Trigger>

        </Style.Triggers>

      </Style>

    </GroupStyle.ContainerStyle>

</ListView.GroupStyle>

 

Here is one using the HierarchicalDataTemplate (I don’t show it here but I could set different alternation counts for each treeview level if I wanted to):   

<!--root tree data template-->

<HierarchicalDataTemplate DataType="{x:Type local:Band}" ItemsSource="{Binding Path=Albums}" >

  <TextBlock Text="{Binding Path=BandName}" />

</HierarchicalDataTemplate>

<!--next level with alternation count set-->

<HierarchicalDataTemplate DataType="{x:Type local:Album}" ItemsSource="{Binding Path=Songs}" AlternationCount="2">

  <TextBlock Text="{Binding Path=AlbumName}" />

</HierarchicalDataTemplate>

<!--leaf-->

<DataTemplate DataType="{x:Type local:Song}">

  <TextBlock Text="{Binding Path=SongName}" />

</DataTemplate>

<TreeView Name="mytv" />                      

 

Here is an example of using a converter to set properties on the control.                       

<!--style using a converter-->

<Style x:Key="alternatingTreeViewItemStyle" TargetType="{x:Type TreeViewItem}">

  <Setter Property="Background" Value="{Binding 

  RelativeSource={RelativeSource Self},

      Path=(ItemsControl.AlternationIndex),

      Converter={StaticResource BGConverter}}"/>

</Style>

<!--treeview using the converter-->

<TreeView Name="mytv2"

  ItemContainerStyle="{StaticResource alternatingTreeViewItemStyle}"

  AlternationCount="2" /> 

// code for convert function

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

{
switch ((int)value)

  {
case 1:

        return Brushes.LightBlue;

      case 2:

        return Brushes.LightGray;

      default:

        return Brushes.White;
}
}

Remember that you aren’t restricted to background color. You can use any DP on the items control to alternate. I’ve attached a project that has all the above examples for you to try out and explore.

 

AlternatingRowSampleApp.zip