d365b
d365b

Reputation: 21

Share ControlTemplate.Triggers between two button' styles

A little help, please ... I have this ResourceDictionary to style buttons. There is a "Base button style" and now I am working on a button which will have a drop down content menu where the user can make a selection. As you will notice in the code below, I had to copy and paste the visual states from the base button style to the dropdown button style if I wanted both button to look the same when focused, mouse over, etc. But what if I have to make a change in the future? Then I will have to remember to apply the change in both styles - perhaps there might be more than 2 styles if this library keeps growing.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- Base button style -->
    <Style x:Key="winFormButton" TargetType="Button">
        <!-- Set Default Background and Border -->
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
        <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="4,2"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Width" Value="73"/>
        <Setter Property="Height" Value="21"/>

        <!-- Control Template -->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>

                    <!-- Visual States -->
                    <ControlTemplate.Triggers>
                        <!-- Mouse Over -->
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Pressed -->
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Disabled -->
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            <Setter TargetName="contentPresenter" Property="Effect">
                                <Setter.Value>
                                    <DropShadowEffect Color="{DynamicResource {x:Static SystemColors.HighlightTextColorKey}}" Direction="660" ShadowDepth="1.2" BlurRadius="0" Opacity="1"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <!-- Focused -->
                        <Trigger Property="IsKeyboardFocused" Value="True">
                            <Setter TargetName="border" Property="BorderThickness" Value="2"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Focused and Mouse Over -->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsKeyboardFocused" Value="True"/>
                                <Condition Property="IsMouseOver" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </MultiTrigger>
                        <!-- Default and Not Focused -->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsDefaulted" Value="True"/>
                                <Condition Property="IsFocused" Value="False"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="BorderThickness" Value="2"/>
                            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Dropdown button style -->
    <Style x:Key="dropdownWinFormButton" TargetType="Button" BasedOn="{StaticResource winFormButton}">
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <Grid>
                                <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="6,-2,0,0"/>
                                <Path HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" Data="M 2 2 L 6 6 L 10 2" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Fill="Transparent"/>
                            </Grid>
                        </Border>
                    </Grid>

                    <!-- Visual States -->
                    <ControlTemplate.Triggers>
                        <!-- Mouse Over -->
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Pressed -->
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Disabled -->
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            <Setter TargetName="contentPresenter" Property="Effect">
                                <Setter.Value>
                                    <DropShadowEffect Color="{DynamicResource {x:Static SystemColors.HighlightTextColorKey}}" Direction="660" ShadowDepth="1.2" BlurRadius="0" Opacity="1"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <!-- Focused -->
                        <Trigger Property="IsKeyboardFocused" Value="True">
                            <Setter TargetName="border" Property="BorderThickness" Value="2"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </Trigger>
                        <!-- Focused and Mouse Over -->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsKeyboardFocused" Value="True"/>
                                <Condition Property="IsMouseOver" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                            <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </MultiTrigger>
                        <!-- Default and Not Focused -->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsDefaulted" Value="True"/>
                                <Condition Property="IsFocused" Value="False"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="BorderThickness" Value="2"/>
                            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

Is there a way to apply the Visual States (i.e. the ControlTemplate.Triggers) to both styles without having to copy the entire code so that when a change/a correction is needed this will be done in a single place?

Upvotes: 0

Views: 46

Answers (1)

d365b
d365b

Reputation: 21

Thank you for the suggestions. I was not able to move the Triggers in ControlTemplate.Triggers to Style.Triggers as many properties were no accessible in Style.Triggers. After scratching my head like a lot I managed to improve this situation using the Property="HorizontalContentAlignment" as trigger to set the content's margin and to show/hide the dropdown arrow. If I decide to add another style things might get trickier but for the time being, this seems to work.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <!-- winFormButtonControlTemplate -->
    <ControlTemplate x:Key="winFormButtonControlTemplate" TargetType="Button">
        <Border x:Name="border"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}">
            <Grid>
                <AccessText x:Name="content"
                            Text="{TemplateBinding Content}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                <Grid x:Name="dropdownArrowGrid" Visibility="Collapsed">
                    <Path VerticalAlignment="Center"
                          HorizontalAlignment="Right"
                          Margin="0,0,5,0"
                          Data="M 2 2 L 6 6 L 10 2"
                          Stroke="{TemplateBinding Foreground}"
                          StrokeThickness="1"
                          Fill="Transparent"/>
                </Grid>
            </Grid>
        </Border>

        <ControlTemplate.Triggers>
            <Trigger Property="HorizontalContentAlignment" Value="Center">
                <Setter TargetName="content" Property="Margin" Value="0,0,0,0"/>
            </Trigger>
            <Trigger Property="HorizontalContentAlignment" Value="Left">
                <Setter TargetName="content" Property="Margin" Value="6,-2,0,0"/>
                <Setter TargetName="dropdownArrowGrid" Property="Visibility" Value="Visible"/>
            </Trigger>
            
            <!-- Mouse Over -->
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
                <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
            </Trigger>
            <!-- Pressed -->
            <Trigger Property="IsPressed" Value="True">
                <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}"/>
                <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
            </Trigger>
            <!-- Disabled -->
            <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="border" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
                <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                <Setter TargetName="content" Property="Effect">
                    <Setter.Value>
                        <DropShadowEffect Color="{DynamicResource {x:Static SystemColors.HighlightTextColorKey}}" Direction="660" ShadowDepth="1.2" BlurRadius="0" Opacity="1"/>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <!-- Focused -->
            <Trigger Property="IsKeyboardFocused" Value="True">
                <Setter TargetName="border" Property="BorderThickness" Value="2"/>
                <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
            </Trigger>
            <!-- Focused and Mouse Over -->
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsKeyboardFocused" Value="True"/>
                    <Condition Property="IsMouseOver" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter TargetName="border" Property="BorderThickness" Value="1"/>
                <Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
            </MultiTrigger>
            <!-- Default and Not Focused -->
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsDefaulted" Value="True"/>
                    <Condition Property="IsFocused" Value="False"/>
                </MultiTrigger.Conditions>
                <Setter Property="BorderThickness" Value="2"/>
                <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
            </MultiTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <!-- winFormButton -->
    <Style x:Key="winFormButton" TargetType="Button">
        <!-- Set Default Background and Border -->
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
        <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="4,2"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Width" Value="73"/>
        <Setter Property="Height" Value="21"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template" Value="{StaticResource winFormButtonControlTemplate}"/>
    </Style>


    <!-- dropdownWinFormButton -->
    <Style x:Key="dropdownWinFormButton" TargetType="Button" BasedOn="{StaticResource winFormButton}">
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
    </Style>


    <!-- Style for MenuItem -->
    <Style TargetType="MenuItem">
        <Setter Property="Command" Value="{Binding DataContext.OpenDropdownCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
    </Style>
</ResourceDictionary>

Upvotes: 0

Related Questions