所以我的xaml代码看起来像这样 -
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
我无法使用GoToVisualState
行为,因为我需要在运行此动画之前进行一些检查。所以我想我必须在后面的代码中调用类似GoToState
或GoToElementState
的内容。
但是, WinRT 中似乎不存在ExtendedVisualStateManager
。我尝试使用
VisualStateManager.GetCustomVisualStateManager(this.LayoutRoot)
但它始终返回null
。
有没有解决方法呢?
答案 0 :(得分:3)
刚想出来。
首先创建一个帮助程序类,就像我们以前在Silverlight或Windows Phone中使用它一样(我从here获取了这段代码并对其进行了一些修改,以便当一个元素没有任何视觉效果时状态组附加,它会自动搜索其父级,直到它找到任何)。
public class ExtendedVisualStateManager : VisualStateManager
{
protected override bool GoToStateCore(Control control, FrameworkElement stateGroupsRoot, string stateName, VisualStateGroup group, VisualState state, bool useTransitions)
{
if ((group == null) || (state == null))
{
return false;
}
if (control == null)
{
control = new ContentControl();
}
return base.GoToStateCore(control, stateGroupsRoot, stateName, group, state, useTransitions);
}
public static bool GoToElementState(FrameworkElement element, string stateName, bool useTransitions)
{
var root = FindNearestStatefulFrameworkElement(element);
var customVisualStateManager = VisualStateManager.GetCustomVisualStateManager(root) as ExtendedVisualStateManager;
return ((customVisualStateManager != null) && customVisualStateManager.GoToStateInternal(root, stateName, useTransitions));
}
private static FrameworkElement FindNearestStatefulFrameworkElement(FrameworkElement element)
{
while (element != null && VisualStateManager.GetCustomVisualStateManager(element) == null)
{
element = element.Parent as FrameworkElement;
}
return element;
}
private bool GoToStateInternal(FrameworkElement stateGroupsRoot, string stateName, bool useTransitions)
{
VisualStateGroup group;
VisualState state;
return (TryGetState(stateGroupsRoot, stateName, out group, out state) && this.GoToStateCore(null, stateGroupsRoot, stateName, group, state, useTransitions));
}
private static bool TryGetState(FrameworkElement element, string stateName, out VisualStateGroup group, out VisualState state)
{
group = null;
state = null;
foreach (VisualStateGroup group2 in VisualStateManager.GetVisualStateGroups(element))
{
foreach (VisualState state2 in group2.States)
{
if (state2.Name == stateName)
{
group = group2;
state = state2;
return true;
}
}
}
return false;
}
}
然后你需要手动将xaml更新为这样的东西 -
<VisualStateManager.CustomVisualStateManager>
<common:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup .../>
</VisualStateManager.VisualStateGroups>
我想这个解决方案的好处在于你仍然可以在Blend的状态标签中看到视觉状态,对于Blend爱好者来说这很酷。
答案 1 :(得分:0)
通常,我的控件中有一个UpdateVisualState(bool useTransitions)
方法可以进行所有GoToVisualState()
次调用。如果某些内容无法动画,那么我会看到两个选项:
UpdateVisualState()
方法中修改代码。此解决方案的缺点是Blend不会在可视状态编辑器中显示更改。我个人并不在乎,因为我很少在已经集成的设计上使用Blend,这个解决方案很简单。Storyboard
为该属性设置动画。这是一项更多的工作,但可以在您的项目中保持Blend支持。