xamlbuttonuwpuwp-xamlvisualstates

Button VisualState Focused not working


I'm trying to change the font color of a button when the button is clicked. I have tried many different things but none have worked. This is the latest thing I tried and what I believe should be the answer but its not working. Can someone help? PointerOver isworking fine, but Focused is not doing anything when the button is clicked.

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Foreground" Value="Black" />
    <Setter Property="FontWeight" Value="Normal" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid
                    x:Name="RootGrid"
                    Background="{TemplateBinding Background}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>

                            <VisualState x:Name="PointerOver">
                                <VisualState.Setters>
                                    <Setter Target="ContentPresenter.FontWeight" Value="Bold" />
                                </VisualState.Setters>
                            </VisualState>

                            <VisualState x:Name="Pressed"/>

                            <VisualState x:Name="Focused">
                                <VisualState.Setters>
                                    <Setter Target="ContentPresenter.Foreground" Value="Purple" />
                                </VisualState.Setters>
                            </VisualState>

                            <VisualState x:Name="Disabled">
                            </VisualState>
                        </VisualStateGroup>

                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter
                        x:Name="ContentPresenter"
                        Content="{TemplateBinding Content}"
                        ContentTransitions="{TemplateBinding ContentTransitions}"
                        ContentTemplate="{TemplateBinding ContentTemplate}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

EDIT based on comments: Adding clarification- I tried using Pressed prior to posting this question but it doesn't do what I'm looking for. After click I want the color to remain applied until another button is clicked, then the text in the new button clicked will change color and the previous button clicked will go back to the default color. With pressed, as soon as you let the mouse button go the text goes back to default.

Edit based Answer suggestions: Also providing surrounding code to see if mistake is being made somewhere else.

    <Page.Resources>
    <Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="FontWeight" Value="Normal" />
        <Setter Property="UseSystemFocusVisuals" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>

                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <Setter Target="ContentPresenter.FontWeight" Value="Bold" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="Pressed"/>

                                <VisualState x:Name="Disabled">
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused">
                                    <VisualState.Setters>
                                        <Setter Target="ContentPresenter.Foreground" Value="Purple" />
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Unfocused" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter x:Name="ContentPresenter"
                      Content="{TemplateBinding Content}"
                    ContentTransitions="{TemplateBinding ContentTransitions}"
                    ContentTemplate="{TemplateBinding ContentTemplate}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button Style="{StaticResource ButtonStyle}" Content="Button" HorizontalAlignment="Left" Margin="10,180,0,0" VerticalAlignment="Top" />
    <Button Style="{StaticResource ButtonStyle}" Content="Button" HorizontalAlignment="Left" Margin="100,180,0,0" VerticalAlignment="Top"/>
    <Button Style="{StaticResource ButtonStyle}" Content="Button" HorizontalAlignment="Left" Margin="194,180,0,0" VerticalAlignment="Top"/>
</Grid>

Solution

  • In UWP, there's a System-level focus visual applied to Button and a lot of other controls by default. If you want to manage your own focus visual like how you defined in your Focused visual state, try setting

    <Setter Property="UseSystemFocusVisuals" Value="False" />
    

    in your style.

    Also, custom focus visual state is not inside CommonStates but FocusStates. So you will need to move your focus state inside

    <VisualStateGroup x:Name="FocusStates">
        <VisualState x:Name="Focused">
            <VisualState.Setters>
                <Setter Target="ContentPresenter.Foreground" Value="Purple" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="Unfocused" />
    </VisualStateGroup>
    

    Update

    When you want to maintain the focus on click, you will want two things. First, you need AllowFocusOnInteraction set to True. By default, it's already True on a Button. Second, you want to handle PointerFocused state along with Focused one. So replace your focus states with the following

    <VisualStateGroup x:Name="FocusStates">
        <VisualState x:Name="Focused">
            <VisualState.Setters>
                <Setter Target="ContentPresenter.Foreground" Value="Purple" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="PointerFocused">
            <VisualState.Setters>
                <Setter Target="ContentPresenter.Foreground" Value="Purple" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="Unfocused" />
    </VisualStateGroup> 
    

    Why? Because two states are happening around the same time when you click a Button - Pressed from CommonStates and PointerFocused from FocusStates. The Focused state is generally triggered when you tap the Tab key.


    <Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="FontWeight" Value="Normal" />
        <Setter Property="FontSize" Value="40" />
        <Setter Property="UseSystemFocusVisuals" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
    
                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <Setter Target="FocusContentPresenter.FontWeight" Value="Bold" />
                                        <Setter Target="ContentPresenter.FontWeight" Value="Bold" />
                                        <Setter Target="ContentPresenter.Foreground" Value="Pink" />
                                    </VisualState.Setters>
                                </VisualState>
    
                                <VisualState x:Name="Pressed">
                                    <VisualState.Setters>
                                        <Setter Target="ContentPresenter.Foreground" Value="Purple" />
                                    </VisualState.Setters>
                                </VisualState>
    
                                <VisualState x:Name="Disabled">
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused">
                                    <VisualState.Setters>
                                        <Setter Target="FocusContentPresenter.Foreground" Value="Purple" />
                                        <Setter Target="FocusContentPresenter.(UIElement.Opacity)" Value="1" />
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="PointerFocused">
                                    <VisualState.Setters>
                                        <Setter Target="FocusContentPresenter.Foreground" Value="Purple" />
                                        <Setter Target="FocusContentPresenter.(UIElement.Opacity)" Value="1" />
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Unfocused" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplate="{TemplateBinding ContentTemplate}" />
                        <ContentPresenter x:Name="FocusContentPresenter" Opacity="0" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplate="{TemplateBinding ContentTemplate}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>