我正在尝试获取对象的当前 VisualState。我在 SO 上找到了一个答案,这是不可能的,在其他地方的另一个博客中我应该能够像这样得到这些:
var currentState = VisualStateManager.GetVisualStateGroups(ContainerGrid);
然而,curentState 似乎什么也没得到。我究竟做错了什么?
我正在尝试获取对象的当前 VisualState。我在 SO 上找到了一个答案,这是不可能的,在其他地方的另一个博客中我应该能够像这样得到这些:
var currentState = VisualStateManager.GetVisualStateGroups(ContainerGrid);
然而,curentState 似乎什么也没得到。我究竟做错了什么?
我发现这个答案对我来说效果更好,因为我不需要任何外部的东西:Silverlight: VisualStateManager.GetVisualStateGroups 不需要,我怎样才能得到它们?
WinRT XAML 工具包具有此扩展方法 -AwaitableUI.ControlExtensions.GoToVisualStateAsync()
使用您提到的方法 ( ) 查找用于视觉状态转换的情节提要,并在调用常规方法VisualStateManager.GetVisualStateGroups()
后等待其完成。VisualStateManager.GoToState()
到目前为止,它对我来说效果很好。唯一需要注意的是,您需要调用GetVisualStateGroups()
指定视觉状态组的元素,因此在大多数情况下,您可能需要深入了解控件模板的视觉树,因为它们通常是在其中定义的——模板中更深的地方比实际的逻辑控制。
这是我的完整示例课程:
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
namespace WinRTXamlToolkit.AwaitableUI
{
/// <summary>
/// Extension methods for Control class.
/// </summary>
public static class ControlExtensions
{
#region GoToVisualStateAsync()
/// <summary>
/// Goes to specified visual state, waiting for the transition to complete.
/// </summary>
/// <param name="control">
/// Control to transition.
/// </param>
/// <param name="visualStatesHost">
/// FrameworkElement that defines the visual states
/// (usually the root of the control's template).
/// </param>
/// <param name="stateGroupName">
/// Name of the state group
/// (speeds up the search for the state transition storyboard).
/// </param>
/// <param name="stateName">
/// State to transition to.
/// </param>
/// <returns>
/// Awaitable task that completes when the transition storyboard completes.
/// </returns>
/// <remarks>
/// If a state transition storyboard is not found - the task
/// completes immediately.
/// </remarks>
public static async Task GoToVisualStateAsync(
this Control control,
FrameworkElement visualStatesHost,
string stateGroupName,
string stateName)
{
var tcs = new TaskCompletionSource<Storyboard>();
Storyboard storyboard =
GetStoryboardForVisualState(visualStatesHost, stateGroupName, stateName);
if (storyboard != null)
{
EventHandler<object> eh = null;
eh = (s, e) =>
{
storyboard.Completed -= eh;
tcs.SetResult(storyboard);
};
storyboard.Completed += eh;
}
VisualStateManager.GoToState(control, stateName, true);
if (storyboard == null)
{
return;
}
await tcs.Task;
}
#endregion
#region GetStoryboardForVisualState()
/// <summary>
/// Gets the state transition storyboard for the specified state.
/// </summary>
/// <param name="visualStatesHost">
/// FrameworkElement that defines the visual states
/// (usually the root of the control's template).
/// </param>
/// <param name="stateGroupName">
/// Name of the state group
/// (speeds up the search for the state transition storyboard).
/// </param>
/// <param name="stateName">
/// State to transition to.
/// </param>
/// <returns>The state transition storyboard.</returns>
private static Storyboard GetStoryboardForVisualState(
FrameworkElement visualStatesHost,
string stateGroupName,
string stateName)
{
Storyboard storyboard = null;
var stateGroups = VisualStateManager.GetVisualStateGroups(visualStatesHost);
VisualStateGroup stateGroup = null;
if (!string.IsNullOrEmpty(stateGroupName))
{
stateGroup = stateGroups.FirstOrDefault(g => g.Name == stateGroupName);
}
VisualState state = null;
if (stateGroup != null)
{
state = stateGroup.States.FirstOrDefault(s => s.Name == stateName);
}
if (state == null)
{
foreach (var group in stateGroups)
{
state = group.States.FirstOrDefault(s => s.Name == stateName);
if (state != null)
{
break;
}
}
}
if (state != null)
{
storyboard = state.Storyboard;
}
return storyboard;
}
#endregion
}
}
这就是我所说的:
await this.GoToVisualStateAsync(_layoutRoot, PopupStatesGroupName, OpenPopupStateName);
this
我的InputDialog
控件在哪里,并且_layoutRoot
是其模板的一部分,定义如下:
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="controls:InputDialog">
<Grid
x:Name="LayoutRoot"
Background="{TemplateBinding BackgroundScreenBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="PopupStates">
<VisualState
x:Name="OpenPopupState">
<Storyboard>
...
提取该视觉状态组后,您可以通过获取stateGroup.CurrentState
.
在 UWP XAML 中,只需将 de VisualStateGroup 命名为:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PopupStates">
<VisualState x:Name="Mobile">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
你得到的名字使用:
PopupStates.CurrentState.Name