WITL
WITL

Reputation: 107

WPF Focused Visual State kicks in only when button pressed, why?

With respect to the code below, can anyone tell me why when a button is in normal state as well as in focused state, the button does not bounce? In other words, shouldn't a button bounce anytime it gets focused state, regardless whether it is pressed or not ?

<Window x:Class="ButtonTemplateUsingVSM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="249" Width="619">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="Background" Value="Black"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid RenderTransformOrigin=".5,.5">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup Name="CommonStates">
                                    <VisualState Name="Normal"/>
                                    <VisualState Name="MouseOver">
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="outerCircle"
                                                            Storyboard.TargetProperty="(Ellipse.Fill).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                            To="Orange" Duration="0:0:.4"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState Name="Pressed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To=".9" Duration="0"/>
                                            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To=".9" Duration="0"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="outerCircle"
                                                            Storyboard.TargetProperty="(Ellipse.Fill).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)"
                                                            To="Gray" Duration="0:0:.4"/>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                                <VisualStateGroup Name="FocusStates">
                                    <VisualState Name="Unfocused"/>
                                    <VisualState Name="Focused">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetProperty="(Grid.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)"
                                                             To="-20" AutoReverse="True" RepeatBehavior="Forever" Duration="0:0:.4">
                                                <DoubleAnimation.EasingFunction>
                                                    <QuadraticEase/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Grid.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform x:Name="scaleTransform"/>
                                    <TranslateTransform x:Name="translateTransform"/>
                                </TransformGroup>
                            </Grid.RenderTransform>
                            <Ellipse x:Name="outerCircle">
                                <Ellipse.Fill>
                                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                        <GradientStop Offset="0"
                                                      Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color}"/>
                                        <GradientStop x:Name="highlightGradientStop" Offset="1" Color="Red"/>
                                    </LinearGradientBrush>
                                </Ellipse.Fill>
                            </Ellipse>
                            <Ellipse RenderTransformOrigin=".5,.5">
                                <Ellipse.RenderTransform>
                                    <ScaleTransform ScaleX=".8" ScaleY=".8"/>
                                </Ellipse.RenderTransform>
                                <Ellipse.Fill>
                                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                        <GradientStop Offset="0" Color="White"/>
                                        <GradientStop Offset="1" Color="Transparent"/>
                                    </LinearGradientBrush>
                                </Ellipse.Fill>
                            </Ellipse>
                            <Viewbox>
                                <ContentPresenter Margin="{TemplateBinding Padding}"/>
                            </Viewbox>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>
    <StackPanel Orientation="Horizontal">
        <Button Height="200" Width="200" FontSize="20" Padding="20" Margin="5">OK</Button>
        <Button Height="200" Width="200" FontSize="20" Padding="20" Margin="5">OK</Button>
        <Button Height="200" Width="200" FontSize="20" Padding="20" Margin="5">OK</Button>
        <Button Height="200" Width="200" FontSize="20" IsEnabled="False" Padding="20" Margin="5">OK</Button>
        <Button Height="200" Width="200" FontSize="20" Padding="20" Margin="5">OK</Button>
    </StackPanel>
</Window>

namespace ButtonTemplateUsingVSM
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Upvotes: 0

Views: 2326

Answers (1)

B.K.
B.K.

Reputation: 10162

By default, a button gets focus only when it's pressed (unless you change it in code). You can also obtain a keyboard focus. Therefore, your bouncing animation will only work when one of those buttons is pressed, due to it being set only for the Focused state:

<VisualStateGroup Name="FocusStates">
    <VisualState Name="Unfocused"/>  <!--Right here-->
    <VisualState Name="Focused">
        <Storyboard>
            <DoubleAnimation Storyboard.TargetProperty="(Grid.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)"
                             To="-20" AutoReverse="True" RepeatBehavior="Forever" 
                             Duration="0:0:.4">
                <DoubleAnimation.EasingFunction>
                    <QuadraticEase/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

As you can see, Unfocused VisualState does not have any animation pertaining to it. So, unless one of those buttons gets the focus, it won't bounce. It'll simply change colors from red to orange per the MouseOver VisualState.

I think this would be a good read for your: MSDN Focus Overview

EDIT:

Explanation for discussion in the comments.

XAML:

<Window x:Class="Focus.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Content="Button 1" HorizontalAlignment="Center" Width="75" Margin="20" GotFocus="Button1_GotFocus"/>
        <Button Content="Button 2" HorizontalAlignment="Center" Width="75" GotFocus="Button2_GotFocus"/>
    </StackPanel>
</Window>

Code-Behind:

using System.Windows;

namespace Focus
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button1_GotFocus(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button 1 Focused");
        }

        private void Button2_GotFocus(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button 2 Focused");
        }
    }
}

Upvotes: 2

Related Questions