VisualStateManager.GoToState(Control, String, Boolean) 方法
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
通过按名称请求新的 VisualState ,在两种状态之间转换控件。
public:
static bool GoToState(Control ^ control, Platform::String ^ stateName, bool useTransitions);
static bool GoToState(Control const& control, winrt::hstring const& stateName, bool const& useTransitions);
public static bool GoToState(Control control, string stateName, bool useTransitions);
function goToState(control, stateName, useTransitions)
Public Shared Function GoToState (control As Control, stateName As String, useTransitions As Boolean) As Boolean
参数
- control
- Control
要进行状态过渡的控件。
- stateName
-
String
Platform::String
winrt::hstring
要转换到的状态。
- useTransitions
-
Boolean
bool
true
使用 VisualTransition 在状态之间转换。
false
使用转换跳过,并直接转到请求的状态。 默认值为 false
。
返回
bool
true
如果控件成功转换为新状态,或已使用该状态,则为 ;否则为 false
。
示例
此示例演示使用 GoToState 方法在状态之间转换的控制逻辑。
private void UpdateStates(bool useTransitions)
{
if (Value >= 0)
{
VisualStateManager.GoToState(this, "Positive", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Negative", useTransitions);
}
if (isFocused)
{
VisualStateManager.GoToState(this, "Focused", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Unfocused", useTransitions);
}
}
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NumericUpDownCustomControl"
>
<Style TargetType="local:NumericUpDown">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:NumericUpDown">
<Grid Margin="3"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ValueStates">
<!--Make the Value property red when it is negative.-->
<VisualState x:Name="Negative">
<Storyboard>
<ColorAnimation To="Red"
Storyboard.TargetName="TextBlock"
Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)"/>
</Storyboard>
</VisualState>
<!--Return the control to its initial state by
return the TextBlock Foreground to its
original color.-->
<VisualState x:Name="Positive" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<!--Add a focus rectangle to highlight the entire control
when it has focus.-->
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual"
Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!--Return the control to its initial state by
hiding the focus rectangle.-->
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderThickness="1" BorderBrush="Gray"
Margin="7,2,2,2" Grid.RowSpan="2"
Background="#E0FFFFFF"
VerticalAlignment="Center"
HorizontalAlignment="Stretch">
<TextBlock x:Name="TextBlock" TextAlignment="Center" Padding="5"
Foreground="{TemplateBinding Foreground}"/>
</Border>
<RepeatButton Content="Up" Margin="2,5,5,0"
x:Name="UpButton"
Grid.Column="1" Grid.Row="0"
Foreground="Green"/>
<RepeatButton Content="Down" Margin="2,0,5,5"
x:Name="DownButton"
Grid.Column="1" Grid.Row="1"
Foreground="Green"/>
<Rectangle Name="FocusVisual" Grid.ColumnSpan="2" Grid.RowSpan="2"
Stroke="Red" StrokeThickness="1"
Visibility="Collapsed"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
注解
控件逻辑使用此方法。 通常,只有在编写自定义控件时,或者对视图状态使用应用级逻辑 ((例如刷新应用内容以更改应用窗口大小或方向) )时才需要它。
调用此方法时,应有一个 VisualState ,该值与 x:Name
值 stateName
匹配,在 控件模板中的某个位置,该控件由 标识 control
,或作为应用的资源。 如果没有,则不会收到异常,但返回值为 false
。 由 命名stateName
的状态可以位于指定控件的模板中的任何 VisualStateGroup 元素中。 由你来跟踪哪些状态处于哪个 VisualStateGroup
状态,并知道在从该组指定新状态时,哪个状态会被卸载。
通常,在使用GoToState
时包含按名称引用的视觉状态的 ControlTemplate 不是为该控件实例专门定义的。 相反,视觉状态来自默认控件样式,该样式作为该控件的所有实例的隐式样式加载。 有关隐式样式概念的详细信息,请参阅 XAML 控件模板。
VisualStateManager 为控件作者和将自定义模板应用于控件的应用开发人员支持两个重要功能:
- 控件作者或应用开发人员使用
VisualStateManager.VisualStateGroups
附加属性将 VisualStateGroup 对象元素添加到 XAML 中的控件模板定义的根元素。 在 元素中VisualStateGroup
,每个 VisualState 表示控件的离散视觉状态。 每个都有VisualState
一个名称,代表可由用户更改或控件逻辑更改的 UI 状态。 主要由VisualState
情节提要组成。 这Storyboard
面向在控件处于该视觉状态时应应用的单个依赖属性值。 - 控件作者或应用开发人员通过调用 VisualStateManager 的静态 GoToState 方法在这些状态之间转换。 每当控件逻辑处理指示状态更改的事件或控件逻辑自行启动状态更改时,控件作者就会执行此操作。 控件定义代码更常见地执行此操作,而不是应用代码,以便应用代码默认存在所有可能的视觉状态及其转换和触发条件。 或者,应用代码正在更改视觉状态,以管理应用级视图状态,以响应用户驱动的对main应用窗口的大小或方向的更改。
调用 GoToState
以更改控件的视觉状态时, VisualStateManager 将执行以下操作:
- 首先确定是否存在匹配
stateName
的状态。 如果没有,则不发生任何操作,并且 方法将返回false
。 - 如果存在命名为 的
stateName
VisualState,并且具有 Storyboard,则情节提要将开始。 - 如果控件在新请求的状态之前从同一 VisualStateGroup 使用的 VisualState 具有 Storyboard,该情节提要将停止。 除了新
VisualState
应用动画的特定属性之外,控件会从控件模板及其合成还原到最初加载的状态。
如果控件已在作为 stateName 请求的 VisualState 中,GoToState
则true
返回 ,但不存在任何操作 (情节提要不会) 重启。
常见的控件实现模式是定义控件类的单个私有方法,用于处理控件的所有可能的 VisualState 更改。 使用哪个视觉状态是通过检查控件的属性确定的。 这些属性可以是公共的,也可以是私有的。 属性的值由事件(例如 OnGotFocus)的控制逻辑中的处理程序进行调整,并在设置视觉状态之前立即进行实时检查。 本主题中的代码示例使用此实现模式。 或者,可以从事件处理程序内部、控件事件处理程序替代 (OnEvent 方法) ,或从所有可能动力调用的帮助程序方法调用 GoToState,以 (更改用户驱动的事件、自动化事件、初始化逻辑) 的状态。
还可以从 PropertyChangedCallback 实现中为自定义依赖属性调用 GoToState。
视觉状态和转换
除了视觉状态,视觉状态模型还包括转换。 切换是由 情节提要 控制的动画操作,在状态更改时,这些动作在每个视觉状态之间发生。 对于由控件的视觉状态集定义的开始状态和结束状态的每种组合,可以以不同的方式定义转换。 转换由 VisualStateGroup 的 Transitions 属性定义,通常在 XAML 中定义。 大多数默认控件模板不定义转换,在这种情况下,状态之间的转换会立即发生。 有关详细信息,请参阅 VisualTransition。
还可以定义 VisualTransition ,使其产生隐式转换。 在 的“ 从 ”或“到 ”视觉状态 VisualTransition
中专门针对动画且在状态更改中具有不同值的任何依赖属性都可以使用隐式过渡动画进行动画处理。 此生成的动画在此类属性的 From 状态值和 To 状态值之间使用内插转换。 隐式过渡动画的持续时间为 的 GeneratedDuration 值所声明的时间 VisualTransition
。 隐式转换仅适用于 双精度值、 颜色 值或 点 值的属性。 换句话说,属性必须能够使用 DoubleAnimation、PointAnimation 或 ColorAnimation 进行隐式动画处理。 有关详细信息,请参阅 GeneratedDuration。
视觉状态更改事件
当控件开始根据调用的请求转换状态时,CurrentStateChanging 将GoToState
触发。 如果 VisualTransition 应用于状态更改,则转换开始时会发生此事件。
CurrentStateChanged 在控件处于调用请求 GoToState
的状态后触发,就像新 Storyboard 开始一样。 新情节提要完成时不会触发任何事件。
如果未应用 VisualTransition , CurrentStateChanging 和 CurrentStateChanged 会快速连续触发,但如果两者都发生,则保证按该顺序运行。
但是,如果状态更改转换被新 GoToState
调用中断,则第一次状态转换永远不会引发 CurrentStateChanged 事件。 为下一个请求的状态更改触发新的事件系列。
不为视觉状态更改调用 OnApplyTemplate。 仅针对控件初始加载到 XAML UI 中调用 OnApplyTemplate。
归因自定义控件的命名视觉状态
如果要定义在其控件模板 XAML 中具有视觉状态的自定义控件,则最佳做法是将控件类归为属性,以指示控件使用者哪些视觉状态可用。 为此,请在控件定义代码的类级别应用一个或多个 TemplateVisualState 属性。 每个属性都应指定状态的 x:Name 属性,该属性是控件使用者在调用中GoToState
传递以使用该视觉状态的 stateName 值。 如果 VisualState 是 VisualStateGroup 的一部分,则应在属性定义中指明这一点。
一个相关概念是,控件作者应使用 TemplatePartAttribute 将关键控件部件的名称归为属性。 如果控件使用者希望在应用模板后从模板范围访问命名部件,这将非常有用。 TemplateVisualStateAttribute 和 TemplatePartAttribute 组合帮助定义控件的控件协定。
自定义 VisualStateManager
作为高级方案,可以从 VisualStateManager 派生并更改默认 GoToState
行为。 派生类应重写受保护的 GoToStateCore 方法。 调用 VisualStateManager 方法时GoToState
,自定义 VisualStateManager 的任何实例都使用此核心逻辑。
应用视图状态的视觉状态
视觉状态不一定适用于自定义控件。 可以通过设置 Template 属性来替换默认模板的任何控件实例使用新控件模板中的视觉状态。 若要进行此设置,必须定义计划用作 或 中的Page.Resources
Application.Resources
样式资源的控件模板和视觉状态。 始终最好从默认模板的副本开始,仅修改模板的某些方面,甚至只修改某些视觉状态,并保留基本组合。 有关详细信息,请参阅 XAML 控件模板。
视觉状态可用于更改 页面或页面中 控件的属性,以考虑应用窗口方向。 组合或控件的布局相关属性值可能会根据整体方向是纵向还是横向而更改。 有关 的此方案 GoToState
的详细信息,请参阅 使用 XAML 的响应式布局。
非控件元素的视觉状态
视觉状态有时对于想要更改 UI 的某些区域(不是 直接作为 Control 子类)的状态的方案非常有用。 无法直接执行此操作,因为 方法的GoToState
控件参数需要一个Control
子类,该子类引用 VisualStateManager 作用的对象。
Page 是一个 Control
子类,很少在没有 Page
的上下文中显示 UI,或者 Window.Content 根不是 Control
子类。 建议将自定义 UserControlWindow.Content
定义为要将状态应用于 (的其他内容的根或容器,例如 Panel) 。 然后,无论其余内容是否为 Control
,都可以调用 GoToState
UserControl
并应用状态。 例如,可以将视觉状态应用于 UI,否则它只包含 SwapChainPanel ,只要将它 UserControl
放置在应用于父 UserControl
级或 SwapChainPanel
模板命名部分的已声明的命名状态中。