WPF Focused Visual State 仅在按下按钮时才会启动,为啥?
Posted
技术标签:
【中文标题】WPF Focused Visual State 仅在按下按钮时才会启动,为啥?【英文标题】:WPF Focused Visual State kicks in only when button pressed, why?WPF Focused Visual State 仅在按下按钮时才会启动,为什么? 【发布时间】:2014-05-12 03:18:37 【问题描述】:关于下面的代码,谁能告诉我为什么当按钮处于正常状态和焦点状态时,按钮不反弹?换句话说,一个按钮不应该在它获得焦点状态时反弹,无论它是否被按下?
<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>
如您所见,Unfocused
VisualState
没有任何与之相关的动画。因此,除非其中一个按钮获得焦点,否则它不会反弹。根据MouseOver
VisualState
,它只会将颜色从红色变为橙色。
我认为这对你来说是一本好书:MSDN Focus Overview
编辑:
在 cmets 中讨论的解释。
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");
【讨论】:
我的印象是这种情况——也就是说,一个按钮只有在按下时才处于焦点状态。但是这个例子取自“WPF 4 unleashed”一书,关于那个例子,有一个插图说明了所有的可能性(例如,MouseOver Unfocused、Disabled、Unfocused)。其中一种可能性是“Normal Focused”,这就是我发布这个问题的原因......在这种情况下,我不确定为什么提到“Normal Focused”作为用户交互可能导致的一种可能组合? @WITL 我不知道正常的专注状态。一个按钮有两个状态组。 CommonStates:Normal、MouseOver、Pressed、Disabled 和 FocuStates:未聚焦、聚焦。这本书可能有错字……很多书都有。我没有这本书,所以我不知道它到底在说什么,但我告诉你的是它是怎样的。这是一个很好的州资源:blogs.msdn.com/b/jeetenk/archive/2009/07/10/… 当您按下并释放按钮时,按钮处于 CommonStates- Normal 和 FocuStates-focused 状态,这可以是“Normal Focused”状态并且按钮仍会弹跳 @WITL 嗯...据我所知,这本书没有免费版本。在遇到麻烦之前删除该链接。但是,请阅读第 645 页底部的内容。它详细描述了我告诉您的内容。那么,当你鼠标悬停时会发生什么?它从正常状态进入鼠标悬停状态。如果按下按钮会发生什么?它从不专注的状态到专注的状态。当您将鼠标从按下的按钮上移开时会发生什么?它从 MouseOver 状态变为 Normal 状态,但是因为动画没有过渡,所以按钮会继续弹跳。 @WITL 因此,按钮只有在获得焦点时才会弹跳。您在问为什么它在 Normal Focused 状态下不反弹,但确实如此。我认为您对什么是 Focus 感到困惑。阅读我在回答中提供的链接,该链接告诉您有关 WPF 中的焦点。接收焦点的方式有很多种,但默认情况下,鼠标悬停不会接收到焦点。以上是关于WPF Focused Visual State 仅在按下按钮时才会启动,为啥?的主要内容,如果未能解决你的问题,请参考以下文章