Chris Mack
Chris Mack

Reputation: 5208

ResourceDictionary Style.Triggers Not Working In UserControl

I have the following Grid in a UserControl, in its own XAML file:

<Grid Style="{StaticResource GridStyle}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="10"/>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="10"/>
        <ColumnDefinition Width="70"/>
    </Grid.ColumnDefinitions>
    <TextBlock x:Name="Box1" Style="{StaticResource ContainedTextBlock}" Grid.Column="0"/>
    <TextBlock x:Name="Box2" Style="{StaticResource ContainedTextBlock}" Grid.Column="2"/>
    <TextBlock x:Name="Box3" Style="{StaticResource ContainedTextBlock}" Grid.Column="4" TextAlignment="Right"/>
</Grid>

In a separate Resource Dictionary XAML file, I have the following:

<SolidColorBrush x:Key="PrimaryColour" Color="#FF334D51"/>
<SolidColorBrush x:Key="BackgroundGray" Color="#FFDEDEDE"/>
<SolidColorBrush x:Key="SelectedGray" Color="#FF566164"/>

<Style TargetType="TextBlock" x:Key="ContainedTextBlock">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{StaticResource PrimaryColour}"/>
    <Setter Property="TextTrimming" Value="WordEllipsis"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
            <Setter Property="Foreground" Value="White"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

<Style TargetType="Grid" x:Key="GridStyle">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="Background" Value="Transparent"/>
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property="Background" Value="{StaticResource BackgroundGray}"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocused" Value="True">
            <Setter Property="Background" Value="{StaticResource SelectedGray}"/>
        </Trigger>
    </Style.Triggers>
</Style>

Can anyone help me on why the Style.Triggers parts are not being picked up at runtime, i.e. the colours of my controls are not changing? (Note: The other parts of the styles are working.)

Upvotes: 1

Views: 1226

Answers (2)

Chris Mack
Chris Mack

Reputation: 5208

I finally got this working.

For the User Control:

<UserControl x:Class="Project.Controls.CustomGrid"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Height="Auto" Width="Auto" Style="{StaticResource GridStyle}">

    <Grid Style="{StaticResource ContainedGrid}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="70"/>
        </Grid.ColumnDefinitions>
        <TextBlock x:Name="Block1" Grid.Column="0" Style="{StaticResource ContainedTextBlock}"/>
        <TextBlock x:Name="Block2" Grid.Column="2" Style="{StaticResource ContainedTextBlock}"/>
        <TextBlock x:Name="Block3" Grid.Column="4" TextAlignment="Right" Style="{StaticResource ContainedTextBlock}"/>
    </Grid>

</UserControl>

In the Resource Dictionary:

    <Style TargetType="UserControl" x:Key="GridStyle">
        <Setter Property="DockPanel.Dock" Value="Top"/>
        <Setter Property="Focusable" Value="True"/>
    </Style>

    <Style TargetType="{x:Type Grid}" x:Key="ContainedGrid">
        <Setter Property="Background" Value="Transparent"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="True">
                <Setter Property="Background" Value="{StaticResource BackgroundGray}"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="True">
                <Setter Property="Background" Value="{StaticResource SelectedGray}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <Style TargetType="{x:Type TextBlock}" x:Key="ContainedTextBlock">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="{StaticResource PrimaryColor}"/>
        <Setter Property="TextTrimming" Value="WordEllipsis"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" Value="True">
                <Setter Property="Foreground" Value="White"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

Another thing to watch out for, the final thing that threw me off, is that the event handler I’m using to give keyboard focus to the User Control didn’t have…

e.Handled = true;

… at the end.

The click was therefore bubbling back and giving the container (a ScrollViewer) the keyboard focus.

To summarise:

  1. The element getting focus is the UserControl.
  2. The Grid and TextBlocks are being formatted based on the focus status of the nearest UserControl in their ancestry.

Upvotes: 0

Peter Duniho
Peter Duniho

Reputation: 70701

The Grid object cannot receive focus (nor can TextBlock for that matter, though that's not immediately relevant in the code posted above). It stands to reason then, that any trigger that is activated only when it does receive focus will itself never be activated.

If you feel otherwise, please provide a good, minimal, complete code example that reliably reproduces the problem. Please be sure to include a precise explanation of how the user should interact with the program such that you would expect these triggers to be activated.

Upvotes: 1

Related Questions