Home > View Post

Reason 4. Triggers

Earlier I introduced a series of posts entitled 10 reasons to consider WPF for your next desktop application. If you haven't read the intro yet, better head on back and read it first.

Trigger Triggers are basically a way of applying a value to a property of an object when an event occurs or a particular condition is satisfied.

Let's look at an example. Again, we'll be using the product of the previous reason and build on that (including the changes made in the post about my dirty little secret).

We're going to pimp our listbox some more. In this scenario, I want to draw attention to my best books and somehow want to highlight books that have a customer rating of 5. Let's look at how to do this with a DataTrigger (a type of trigger).

<DataTemplate x:Key="listTemplate">
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding CustomerRating}" Value="5" >
            <Setter TargetName="_bookName" Property="TextBlock.FontWeight" Value="Bold" />
            <Setter TargetName="_ratingBar" Property="src:RatingBar.Fill" Value="Red" />
        </DataTrigger>
    </DataTemplate.Triggers>

    <!-- snipped for brevity -->
    
    <TextBlock x:Name="_bookName" Text="{Binding Name}" />
    <src:RatingBar x:Name="_ratingBar" Value="{Binding CustomerRating}" ... />

As you can see, we've added a new DataTrigger to our DataTemplate's Triggers collection. This DataTrigger is bound to the CustomerRating and is waiting for a Value of 5 before it will 'fire'. This is when the Setters inside are applied.

A Setter is a pretty simple idea - it sets the value of a property. In the example above we set the FontWeight of the TextBlock (with the name _bookName) to Bold.

We also have a second Setter that changes the Fill of our new RatingBar to Red.

Et Voila!

Bold and Red for the 5* books

Too easy. There are more, and perhaps more useful scenarios where Triggers can help you. It is a very common requirement that we have one part of our view disabled based upon the state of another part. For example, in our example UI the textboxes on the left should be disabled if no books are selected in the listbox.

form on the right should be disabled

This makes sense right? You don't want you user typing when we're not bound to an object. All we need to do is disable (set IsEnabled=False) on the GroupBox containing the listboxes based on the SelectedIndex listbox:

<GroupBox Header="Book Details" DataContext="{Binding ElementName=_lstBooks, Path=SelectedItem}" Margin="3" Grid.Column="1" >
    <GroupBox.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=_lstBooks, Path=SelectedIndex}" Value="-1">
                    <Setter Property="GroupBox.IsEnabled" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </GroupBox.Style>

form disabled until an item is selected

To achieve this we simply use a DataTrigger within the style of the GroupBox. And it works a treat, even if your listbox supports deletion (i.e. when you delete an item from the list of books, if this means an item is no longer selected in the listbox then the GroupBox will be disabled). To prove this I've added some simple functionality to add and remove books to the list.

Why not have a play with the Reason 4 ClickOnce Sample.

I'll put the code up for download at the end of the series.

PS - Just for fun, I made the Orange RatingBar interactive. You can click and drag it and actually change the value of the CustomerRating.

Tags: WPF

 
Josh Post By Josh Twist
11:46 AM
20 Oct 2007

» Next Post: LINQPad and the LINQPad challenge
« Previous Post: My dirty little secret from Reason 3. ControlTemplates

Comments are closed for this post.

© 2005 - 2017 Josh Twist - All Rights Reserved.