WPF聚焦视觉状态仅在按下按钮时启动,为什么?

时间:2014-05-12 03:18:38

标签: wpf visualstates

关于下面的代码,任何人都可以告诉我为什么当按钮处于正常状态以及处于聚焦状态时,按钮不会反弹?换句话说,无论是否按下按钮,任何时候按钮都不会反弹;无论是否被按下?

<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 个答案:

答案 0 :(得分: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>

如您所见,Unfocused VisualState没有任何与之相关的动画。因此,除非其中一个按钮获得焦点,否则它不会反弹。它只会根据MouseOver VisualState将颜色从红色更改为橙​​色。

我认为这对你的好读: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>

<强>代码隐藏:

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