WPF Focused Visual State срабатывает только при нажатии кнопки, почему?

Что касается приведенного ниже кода, может ли кто-нибудь сказать мне, почему, когда кнопка находится в нормальном состоянии, а также в сфокусированном состоянии, кнопка не отскакивает? Другими словами, не должна ли кнопка отскакивать всякий раз, когда она находится в состоянии фокусировки, независимо от того, нажата она или нет?

<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();
        }
    }
}

1 ответ

По умолчанию кнопка получает фокус только при нажатии (если вы не изменили ее в коде). Вы также можете получить фокус клавиатуры. Таким образом, ваша подпрыгивающая анимация будет работать только при нажатии одной из этих кнопок, поскольку она настроена только для Focused государство:

<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>

Как вы видете, UnfocusedVisualState не имеет никакой анимации, относящейся к нему. Таким образом, если одна из этих кнопок не окажется в фокусе, она не отскочит. Это просто изменит цвет с красного на оранжевый в соответствии с MouseOverVisualState,

Я думаю, что это было бы хорошим чтением для вашего: MSDN Focus Overview

РЕДАКТИРОВАТЬ:

Объяснение для обсуждения в комментариях.

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");
        }
    }
}
Другие вопросы по тегам