#1,204 – Using a DataTrigger to Change Content in a ContentPresenter

You can set the ContentTemplate property of a ContentPresenter to a panel containing some content, using a DataTemplate.

This technique becomes even more useful when you have different types of content to display, depending on a particular state in your application. In the example below, we set up a Style for a ContentPresenter that sets default content for the ContentPresenter and then swaps in entirely different content when the JobDone property in the data context becomes true.

    <Window.Resources>
        <DataTemplate x:Key="DefaultContent">
            <StackPanel>
                <TextBlock Margin="10" Text="Some default content here.."/>
                <TextBlock Margin="10" Text="Maybe show progress for operation"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="AllDoneContent">
            <StackPanel>
                <TextBlock Margin="10" Text="** This is the ALL DONE content..."
                           Foreground="Green"/>
                <TextBlock Margin="10" Text="Put anything you like here"/>
                <Button Margin="10" Content="Click Me" HorizontalAlignment="Left"/>
            </StackPanel>
        </DataTemplate>

        <Style x:Key="MyContentStyle" TargetType="ContentPresenter">
            <Setter Property="ContentTemplate" Value="{StaticResource DefaultContent}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding JobDone}" Value="True">
                    <Setter Property="ContentTemplate" Value="{StaticResource AllDoneContent}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
        
    </Window.Resources>
    
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <ContentPresenter Grid.Row="0" Style="{StaticResource MyContentStyle}" Content="{Binding}"/>
        
        <Separator Grid.Row="1"/>

        <CheckBox Grid.Row="2" Margin="10" Content="Mark job done" IsChecked="{Binding JobDone}"/>
    </Grid>

Here’s how the application looks in the two states. Note that we can toggle between the two states using the CheckBox.

#666 – Using a Trigger to React to the Mouse Being Over a Control

You can perform some action when the user moves the mouse over a user interface element by defining event handlers for the MouseEnter and MouseLeave events for the element.

If the action that you’re performing is something that can be expressed in XAML (like setting a property value), it’s more elegant to use a trigger to react to the mouse movement.

You can define a property trigger for the IsMouseOver property, setting new values for one or more of the Button’s properties when the mouse is over the Button.

    <StackPanel Margin="20" >
        <Button HorizontalAlignment="Center" Padding="10,5">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="Content" Value="Click Me"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Button.Content" Value="!! CLICK Me !!"/>
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>



Note that when you move the mouse off of the Button, the Content and FontWeight properties both revert back to their original values.

#130 – WPF Supports Three Types of Triggers

WPF supports three different types of triggers:

  • Property triggers
    • Fire when the value of a dependency property changes
    • Specifies trigger property using property name
    • Actions
      • Setter elements set values for one or more dependency properties
      • One or more TriggerAction classes fire, when trigger becomes active or becomes inactive
  • Data triggers
    • Fire when the value of a CLR property changes
    • Specifies property using Binding keyword
    • Actions
      • Setter elements sets values for one or more dependency properties
      • One or more TriggerAction classes fire, when trigger becomes active or becomes inactive
  • Event triggers
    • Fire when a routed event is raised
    • Action: Class that derives from TriggerAction fires, e.g. BeginStoryboard or SoundPlayerAction
    • Often used for animations

#129 – Properties Changed by Triggers Are Automatically Reset

When you change a property value using a property trigger, the original value of the property will be restored once the conditions of the trigger are no longer true.

For example, you could create a style that applies a drop shadow to a button whenever the user hovers over it, then apply the style to several buttons, as follows:

    <Window.Resources>
        <Style x:Key="hoverStyle" TargetType="Button">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Button.Effect">
                        <Setter.Value>
                            <DropShadowEffect/>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
        <Button Content="Run" Height="23" Width="75" Style="{StaticResource hoverStyle}"/>
        <Button Content="Skip" Height="23" Width="75" Style="{StaticResource hoverStyle}"/>
        <Button Content="Jump" Height="23" Width="75" Style="{StaticResource hoverStyle}"/>
    </StackPanel>

As you hover over a button, it gets a drop shadow.

Notice, however, that as you move on to the next button, the value of IsMouseOver for the first button becomes false and the original value of the Button.Effect property is restored–i.e. the drop shadow is automatically removed.