Search code examples
c#buttonuwptemplate10visualstates

UWP VisualState - Modifying entire class (Button for example)


in UWP, we can easily change the properties of a button for example based on the window size, using the visualstate.setters

<VisualState x:Name="VisualStateNarrow" >
    <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowHeight="{StaticResource NarrowMinHeight}" />
            </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="btnTest.Height" Value="100"/>
                    <Setter Target="btnTest.Width" Value="100"/>
                    ....
                </VisualState.Setters>
            </VisualState>
....

Now let's say I have a large number of buttons. Instead of manually typing each entry, btnA.Height.., BtnB.Height... and so on, is there a way maybe to enter them within the custom.xaml?

I was trying something like:

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

<x:Double x:Key="CustomHeightN">100</x:Double>
<x:Double x:Key="CustomWidthN">100</x:Double>

<ResourceDictionary.ThemeDictionaries
    <ResourceDictionary x:Key="VisualStateNarrow" >
        <Style TargetType="Button">
            <Setter Property="Height" Value="{ThemeResource CustomHeightN}" />
            <Setter Property="Width" Value="{ThemeResource CustomWidthN}" />
        </Style>
    </ResourceDictionary>
....

But of course, it does not work. Could anyone suggest something by a chance?


Solution

  • The easiest way is to override the button template and add your state to its VisualStateManager.

    Here, I've created a new AdaptiveGroup in the existing state manager which will change the Width and Height of the button root grid (some part of the style have been removed for clarity)

    <Style TargetType="Button">      
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="buttonRoot">
                                <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates" />
                                <VisualStateGroup x:Name="FocusStates" />
    
                                <VisualStateGroup x:Name="AdaptiveGroups">
                                        <VisualState x:Name="narrow" />
                                        <VisualState x:Name="wide">
                                            <VisualState.StateTriggers>
                                                <AdaptiveTrigger MinWindowWidth="800" />
                                            </VisualState.StateTriggers>
                                            <VisualState.Setters>
                                                <Setter Target="buttonRoot.Width" Value="200" />
                                                <Setter Target="buttonRoot.Height" Value="200" />
                                            </VisualState.Setters>
                                        </VisualState>
                                    </VisualStateGroup>
    
                                </VisualStateManager.VisualStateGroups>
    
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    

    The full code:

    <Page
        x:Class="ButtonVisualStateManager.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:ButtonVisualStateManager"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <Style TargetType="Button">
                <Setter Property="Background" Value="{ThemeResource ButtonBackgroundThemeBrush}" />
                <Setter Property="Foreground" Value="{ThemeResource ButtonForegroundThemeBrush}"/>
                <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderThemeBrush}" />
                <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
                <Setter Property="Padding" Value="12,4,12,4" />
                <Setter Property="HorizontalAlignment" Value="Left" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
                <Setter Property="FontWeight" Value="SemiBold" />
                <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="buttonRoot">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="PointerOver">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                                   Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverBackgroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                   Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                                   Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                   Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                                   Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBackgroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                                   Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBorderThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                   Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledForegroundThemeBrush}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                                    <VisualStateGroup x:Name="FocusStates">
                                    <VisualState x:Name="Focused">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="1"
                                                     Duration="0" />
                                            <DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="1"
                                                     Duration="0" />
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Unfocused" />
                                    <VisualState x:Name="PointerFocused" />
                                </VisualStateGroup>
    
                                    <VisualStateGroup x:Name="AdaptiveGroups">
                                        <VisualState x:Name="narrow" />
                                        <VisualState x:Name="wide">
                                            <VisualState.StateTriggers>
                                                <AdaptiveTrigger MinWindowWidth="800" />
                                            </VisualState.StateTriggers>
                                            <VisualState.Setters>
                                                <Setter Target="buttonRoot.Width" Value="200" />
                                                <Setter Target="buttonRoot.Height" Value="200" />
                                            </VisualState.Setters>
                                        </VisualState>
                                    </VisualStateGroup>
    
                                </VisualStateManager.VisualStateGroups>
                                <Border x:Name="Border"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Margin="3">
                                <ContentPresenter x:Name="ContentPresenter"
                                          Content="{TemplateBinding Content}"
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          Margin="{TemplateBinding Padding}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                          AutomationProperties.AccessibilityView="Raw"/>
                            </Border>
                                <Rectangle x:Name="FocusVisualWhite"
                                   IsHitTestVisible="False"
                                   Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
                                   StrokeEndLineCap="Square"
                                   StrokeDashArray="1,1"
                                   Opacity="0"
                                   StrokeDashOffset="1.5" />
                                <Rectangle x:Name="FocusVisualBlack"
                                   IsHitTestVisible="False"
                                   Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
                                   StrokeEndLineCap="Square"
                                   StrokeDashArray="1,1"
                                   Opacity="0"
                                   StrokeDashOffset="0.5" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    
        </Page.Resources>
    
        <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Button Content="button 1" />
            <Button Content="button 2" />
            <Button Content="button 3" />
            <Button Content="button 4" />
    
        </StackPanel>
    </Page>