Page 1 of 1

WPF - Using Data Triggers

#1 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1524
  • View blog
  • Posts: 5,960
  • Joined: 21-March 08

Posted 28 February 2011 - 08:04 AM

Data triggers are a great feature of WPF. They allow you to change the style properties of a control depending on the data of the bound items of that control.

In this tutorial, I am going to bind a set of data to a LiztBox, and use Data Triggers to let me know when something is wrong.

So first, I am going to create a Person class. This class will have three public properties: Name, Age, and IsValid. All three properties will be readonly. The IsValid property will return whether the data of the class is good or not.

Person.cs
public class Person
{
    private string name;

    public string Name
    {
        get { return name; }
        private set { name = value; }
    }
    private int age;

    public int Age
    {
        get { return age; }
        private set { age = value; }
    }

    public bool IsValid
    {
        // will return false if either the name is blank 
        //   or if the age is 0.
        get { return (!string.IsNullOrEmpty(name) && age != 0); }
    }

    public Person(string _name, int _age)
    {
        name = _name;
        age = _age;
    }
}



This is a simple example to show the concept. Basically, I am going to set the data to values that we don't want.

MainWindows.xaml.cs
public partial class MainWindow : Window
{
    ObservableCollection<Person> col;

    public MainWindow()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        col = new ObservableCollection<Person>();
        col.Add(new Person("John Doe", 24));
        col.Add(new Person("", 24));
        col.Add(new Person("John Doe", 0));

        PersonListBox.ItemsSource = col;
    }
}



As you can see, I set the name to being blank for one object, and the age to being 0 for another object.

Now for the XAML. First, we need to add a new style to the window.Resources. This style will target the ListBoxItem type.

<window.Resources>
    <Style TargetType="{x:Type ListBoxItem}" x:Key="ItemStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsValid}" Value="false">
                <Setter Property="Background" Value="Red" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</window.Resources>



So if our IsValid property is false, then we will set the Background property of the ListBoxItem to Red.

Then we have our ListBox,

<Grid>
    <ListBox 
        Name="PersonListBox" 
        ItemsSource="{Binding}"
        ItemContainerStyle="{StaticResource ItemStyle}"
        Height="142" 
        HorizontalAlignment="Left" 
        Margin="39,30,0,0" 
        VerticalAlignment="Top" 
        Width="190">

        <ListBox.ItemTemplate>
            
            <DataTemplate>
                
                <StackPanel Orientation="Vertical">
                    
                    <StackPanel Orientation="Horizontal">
                        
                        <TextBlock 
                            Text="Name:" 
                            Width="50" />

                        <TextBlock 
                            Text="{Binding Name}" 
                            Width="150"  />

                    </StackPanel>
                    
                    <StackPanel Orientation="Horizontal">
                        
                        <TextBlock 
                            Text="Age:" 
                            Width="50" />

                        <TextBlock 
                            Text="{Binding Age}" 
                            Width="50"  />

                    </StackPanel>
                    
                </StackPanel>
                
            </DataTemplate>
            
        </ListBox.ItemTemplate>

    </ListBox>
</Grid>



So I am binding the ItemsSource to the collection in the code-behind. Also notice that I am binding the style we created to the ItemContainerStyle. The DataTemplate simply creates a custom ItemTemplate to show the data.

So now if we run our code, we get this...

Attached Image

But that's not all. Let's say that we want to highlight the rows in different colors depending on if the name is blank or if the age is 0. We can create two separate triggers for that. We would simply change our style to this...

<window.Resources>
    <Style TargetType="{x:Type ListBoxItem}" x:Key="ItemStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Name}" Value="">
                <Setter Property="Background" Value="Blue" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Age}" Value="0">
                <Setter Property="Background" Value="Yellow" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</window.Resources>



With that change, our ListBox now shows this...

Attached Image

As you can see, Data Triggers are a very powerful part of WPF. Now if only Microsoft would add this to Silverlight.

Is This A Good Question/Topic? 3
  • +

Replies To: WPF - Using Data Triggers

#2 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4498
  • View blog
  • Posts: 7,850
  • Joined: 08-June 10

Posted 28 February 2011 - 09:12 AM

Man, I could have really used these in my recent project. You should see the hoops I jumped through to make things happen to my bound rows and objects.

I actually made several IValueConverter classes to make Booleans into Visibilities and such.

I'll be happy when it makes its way into Silverlight as well. Perhaps SL5. They seem to be steadily moving forward with features.

This post has been edited by insertAlias: 28 February 2011 - 09:13 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1