我经常发现需要包含“离开”和“当前”类型的视觉状态,这些状态用于根据其他条件设置控件离开或可见的动画。
“离开”状态通常应该是初始状态。据我了解,没有办法在 SL 中定义初始状态,而是“base”,它根本不是一个真正的状态,而是表示状态管理器尚未激活时的外观(没有状态 Storyboard正在运行更改控件的外观)。
当然,您可以将“基础”设计为看起来像“离开”,但这意味着 Expression Blend 中的默认外观是不可见的(您也不能永久“固定”状态)。
为了改变我试过的初始状态
所以问题似乎是无论视觉状态管理器做什么,它都不会立即执行,而是需要一个明显的瞬间来改变外观。
(当然,直接为 bootstrap 设置属性是另一种选择,但仅适用于 UserControls:在模板化控件中,我必须引入另一个 depprop 来模板绑定(bind)控件模板,我认为这是矫枉过正的开始。)
我想我已经涵盖了所有内容,而我只需要忍受一个看不见的基本状态吗?
我用的是 SL4。
最佳答案
我在开发 时遇到了类似的问题用户控制 用于 Expression Blend 中的 WPF(注意:如果您正在开发自定义控件,请参阅我的下一部分)。在那个 UserControl 中,我有一个子元素,我想淡入并成长为覆盖层。像您的情况一样,在我的工作流程中,首先将覆盖元素设计为“完全增长和可见”状态,然后将其缩小并将其不透明度设置为“隐藏”状态是有意义的。在执行此操作时,覆盖在 Base 状态下可见,但我需要 UserControl 的初始状态为 Hidden 状态。在这一点上,我有三个主要的相关状态:基本、“隐藏”和“可见”(最后两个是状态组的一部分)。
以下是我解决初始状态问题的方法 .首先,我将 GoToStateAction 应用于由 Loaded 事件触发的根元素(到 UserControl)。它告诉 UserControl 直接进入“隐藏”状态:
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:GoToStateAction TargetObject="{Binding ElementName=userControl}" StateName="Hidden"/>
</i:EventTrigger>
</i:Interaction.Triggers>
其次,我在 State Group 中为叠加层进行了适当的过渡设置。可能有几种方法可以做到这一点,但我是这样做的。首先,我将“默认过渡”设置为令人愉悦的设置,例如 0.4 秒。接下来,我将任何元素(Blend 中的星形图标)到此“隐藏”状态的转换时间设置为 0 秒(这允许上述 GoToStateAction 设置“初始”状态而用户不知道任何不同)。然后,我将“可见”状态到“隐藏”状态的转换设置为适当的设置(例如 0.4 秒)。基本上,这涵盖了过渡的所有基础。关键是确保从“任何元素”到“隐藏”状态的“转换”是立即的,然后在从覆盖的“可见”状态到“隐藏”状态的情况下覆盖该立即转换。
设置 的初始 VisualState自定义控件
如果您正在开发自定义控件(而不是 UserControl)并因此在控件模板中定义 VisualStateManager,则上述方法(基于 Loaded 事件启动 VisualState 更改)可能不起作用。这是因为控件的可视化树(在样式文件中定义)在
OnApplyTemplate()
之前应用到控件。 override 被调用,通常在第一个 Loaded
之后事件已触发。因此,如果您尝试启动 VisualState 更改以响应自定义控件的 Loaded 事件,很可能不会发生任何事情。 相反,您需要在 OnApplyTemplate()
中启动状态更改。 覆盖代码:public class MyCustomControl : ContentControl
{
// ... other code ....
public MyCustomControl()
{
// avoid designer errors
if (DesignerProperties.GetIsInDesignMode(this))
return;
Loaded += new RoutedEventHandlerMyCustomControl_Loaded);
}
// This probably won't be called until AFTER OnApplyTemplate() gets
// called, so don't expect for your control to even have a visual tree
// yet when your control is first being contructed at runtime.
private void MyCustomControl_Loaded(object sender, RoutedEventArgs e)
{
}
public override void OnApplyTemplate()
{
// Avoid Visual Studio 2010 designer exceptions
// (Visual Studio can't handle the VisualState change at design-time)
if (DesignerProperties.GetIsInDesignMode(this))
return;
base.OnApplyTemplate();
// Now we know that the template has been applied, we have a visual tree,
// so state changes will work
VisualStateManager.GoToState(this, "MyInitialState", false);
}
}
关于silverlight - Silverlight 中的 VisualStateManager : setting an initial state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9521086/