Monday, March 9, 2009

WPF Data Binding - DataTriggers

WPF Data Triggers comes handy when you need to change the appearance of a bound data object when its property values meet a certain condition. For e.g.: You need to show the failed students result in Red.
Like the System.Windows.Style and System.Windows.Controls.ControlTemplate classes, the DataTemplate class has a collection of triggers. A trigger applies property values or performs actions when the bound data meets a specified condition. To create a Data Trigger we need to configure 3 components on the Data Trigger.
1. A Binding property that specifies the property of the data object it should be bound to
2. A value property that the bound property should contain in order for the trigger to be applied
3. A collection of Setters property that contains a collection of System.Windows.Setter objects, which describe the appearance property values to apply when the bound property has the specified value
The following example demonstrates a simple student result window which highlights the failed students in a Red background. The IValueConverter implementation allows the user to change the state of the student by checking or unchecking the check box that indicates the result.
<Window.Resources> <local:ResultConverter x:Key="resultConverter" />
<Style x:Key="textBlockBasicStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="8" />
<Setter Property="Width" Value="200" />
</Style>
<DataTemplate x:Key="studentTemplate" >
<Border BorderBrush="Black" BorderThickness="1" Margin="5">
<StackPanel x:Name="resultPanel" Background="LimeGreen" Width="250" Height="40" VerticalAlignment="Center" Orientation="Horizontal" >
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource textBlockBasicStyle}" />
<CheckBox Margin="8" IsChecked="{Binding Path=Result, Converter={StaticResource resultConverter}}" HorizontalAlignment="Right" VerticalAlignment="Center" />
</StackPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Result, Converter={StaticResource resultConverter}}" Value="False">
<Setter TargetName="resultPanel" Property="Background" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources><StackPanel>
<ListBox ItemTemplate="{StaticResource studentTemplate}" Name="studentList" /></StackPanel>
The code behind file contents is
this.studentList.ItemsSource = new List
{
new Student { Name="Joe", Result="Passed" },
new Student { Name="William", Result="Passed" },
new Student { Name="Sandra", Result="Failed" },
new Student { Name="Glady", Result="Passed" },
new Student { Name="Allan", Result="Passed" },
new Student { Name="Mike", Result="Failed" },
new Student { Name="Rahul", Result="Passed" }
};

Finally the IValueConverter implementation.
public class ResultConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string grade = value.ToString();
bool result = false;
switch (grade)
{
case "Passed":
result = true;
break;
case "Failed":
result = false;
break;
default:
result = false;
break;
}
return result;
}

object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool isChecked = false;
if (bool.TryParse(value.ToString(), out isChecked))
{
return isChecked ? "Passed" : "Failed";
}
return "Failed";
}
}

Output

No comments: