WPF ItemsControl with alternating item and hover effect

by munnaonc 24. April 2009 19:53

Introduction

In this short article we are going to see few tricks about WPF ItemsControl. ItemsControl is one of the simplest yet powerful control in WPF. ItemsControl is just like the repeater control in asp.net. It supports Binding and supports custom template to display the data. for detail study about power of ItemsControl please read MSDN documentation here. In this article we going to focus on how to display alternating item in ItemsControl and apply few effects on items of ItemsControl.

ItemsControlAlternatingItem

Use Alternating Item Style

Items control can be used to display data both via populating the ItemsControl.Items collection or specify a Items Source in ItemControl.ItemsSource property. In this example we are going to use ItemsSource to display our data. Lets assume we have a custom class called country and we want to display the information about country in a ItemsControl. Bellow a simple code listing is given to get the total idea.

public partial class Window1 : Window
{
public Window1()
{
loadDemoData();
this.DataContext = this;
}

public static readonly DependencyProperty DataListProperty =
DependencyProperty.Register(
"DataList", typeof(ObservableCollection<Country>),
typeof(Window1));

private void loadDemoData()
{
ObservableCollection<Country> data =
new ObservableCollection<Country>();
Country c1 = new Country { ID = "1", Name = "Bangladesh",
Capital = "Dhaka", Continent = "Asia" };
Country c2 = new Country { ID = "2", Name = "India",
Capital = "Delhi", Continent = "Asia" };
Country c3 = new Country { ID = "3", Name = "U.S.A",
Capital = "Washington", Continent = "North America" };
Country c4 = new Country { ID = "4", Name = "Australia",
Capital = "Canbarra", Continent = "Australia" };
Country c5 = new Country { ID = "5", Name = "Kenya",
Capital = "", Continent = "Africa" };
data.Add(c1);
data.Add(c2);
data.Add(c3);
data.Add(c4);
data.Add(c5);
this.SetValue(Window1.DataListProperty, data);
}

public class Country
{
public string ID { get; set; }
public string Name { get; set; }
public string Continent { get; set; }
public string Capital { set; get; }
}
}
 
In few of example given in the online community I have seen that items control is not directly been used to display the idea of alternating items, rather list box or perhaps more higher level control is shown to display alternating items. In this section we will see how we can add styles in items and alternating items of ItemsControl just by using a simple DataTemplate. When we use ItemsControl, items of  ItemsControl are generally rendered inside a ContentPresenter, which have only few basic properties, and we can not assign the background or foreground.
 
Using DataTemplate and use smart use of styles on DataTemplate might just solve our problem. Bellow a complete code listing is give, how to do the intended effect.
 
<Window x:Class="WPFDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ItemsControl" MinHeight="350"
MinWidth="550" Background="#f5f5f5">
<Window.Resources>
<Style x:Key="alternatingWithTriggers"
TargetType="{x:Type ContentPresenter}">
<Setter Property="Height" Value="25"></Setter>
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Border x:Name="yahoo">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Name}"></Label>
<Label Content="is in"></Label>
<Label Content="{Binding Continent}"></Label>
</StackPanel>
</Border>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#e9e9e9"
TargetName="yahoo"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#d9d9d9"
TargetName="yahoo"></Setter>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<Grid MinHeight="350" MinWidth="550">
<ItemsControl ItemsSource="{Binding DataList}"
ItemContainerStyle="{StaticResource alternatingWithTriggers}"
AlternationCount="2"
ItemTemplate="{StaticResource MyItemTemplate}"/>
</Grid>
</Window>
 
In above code listing we didn't did any style change in item container styles, rather we override the item template and used the item templates style in such a way so that it shows alternate items style. Main engine to make go this trick is AlternatingItemIndex property of ItemsControl. In data template we used trigger to check the index of item and then apply style to DataTemplates one of inner elements.

Hover Effect

Applying hover effect is now easy since we know how to apply styles using trigger. but in this case we wont use AlternatingItemIndex. We want to apply a mouse over effect regardless of whether its item or alternating item. Bellow the code snippet is give for hover effect on items.

<Style x:Key="onmouseover" TargetType="{x:Type StackPanel}"> 
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Yellow">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Border x:Name="yahoo">
<StackPanel Orientation="Horizontal"
Style="{StaticResource onmouseover}">
<Label Content="{Binding Name}"></Label>
<Label Content="is in"></Label>
<Label Content="{Binding Continent}"></Label>
</StackPanel>
</Border>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#e9e9e9"
TargetName="yahoo"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#d9d9d9"
TargetName="yahoo"></Setter>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
 
In above code snippet you can see that we have applied the style on stack panel. Style of hover on border that is the parent control of data template will not work, since we have already added styles using trigger in Data template. so we defined separate style for stack panel and applied to it. And that concludes are mission.
 

Summery

In this short article we have seen how we can use alternating item using ItemsControl. In this demonstration we have used AlternatingItemCount as 2, but user can set grater than two, but to get the alternating item effect it must be larger than 1. The styles must be modified to support according to AlternatingItemCount. for more study on ItemsControl please visit the references.

Reference

Comments are closed