我经常发现需要包含“离开”和“现在”类型的视觉状态,这些视觉状态用于根据某些其他条件为控件移动或显示设置动画。
然后,“离开”状态通常是应该是初始状态的状态。根据我的理解,没有办法在SL中定义初始状态,而是“base”,这根本不是一个状态,而是表示状态管理器尚未激活的状态(没有状态故事板运行到改变控件的外观。)
当然你可以设计“base”看起来像“离开”,但这意味着Expression Blend中的默认外观是不可见的(你不能永久地“固定”状态)。
要更改我尝试的初始状态
所以问题似乎是无论视觉状态管理器做了什么,它都没有立即执行,但需要一个明显的瞬间来改变外观。
(直接为bootstrap设置属性当然是另一种选择,但只适用于UserControls:在模板化控件中,我必须引入另一个depprop模板绑定控件模板,这是我认为overkill开始的地方。 )
我想我已经覆盖了所有这些,我只能忍受一个看不见的基础状态?
我使用SL4。
答案 0 :(得分:6)
我在Expression Blend中为WPF开发 UserControl 时遇到了类似的问题(注意:如果您正在开发自定义控件,请参阅下一节)。在那个UserControl中,我有一个我希望淡入的子元素,并作为叠加层存在。与您的情况一样,在我的工作流程中首先将覆盖元素设计为“完全成长和可见”状态,然后将其缩小并将其不透明度设置为“隐藏”状态。这样做,覆盖在Base状态下可见,但我需要UserControl的初始状态为隐藏状态。在这一点上,我有三个主要的相关状态:Base,“Hidden”和“Visible”(最后两个是State组的一部分)。
以下是我解决初始状态问题的方法。首先,我将GoToStateAction应用于由Loaded事件触发的根元素(到UserControl)。它告诉UserControl直接进入“隐藏”状态:
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:GoToStateAction TargetObject="{Binding ElementName=userControl}" StateName="Hidden"/>
</i:EventTrigger>
</i:Interaction.Triggers>
其次,我在状态组中为叠加层进行了适当的转换设置。可能有几种方法可以做到这一点,但这就是我如何做到的。首先,我将“默认转换”设置为令人满意的设置,比如说.4秒。接下来,我将从任何元素(Blend中的星形图标)到此“隐藏”状态的转换时间设置为0秒(这允许上述GoToStateAction设置“初始”状态,而用户不知道任何不同)。然后,我将从“可见”状态到“隐藏”状态的转换设置为适当的设置(比如.4秒)。基本上这涵盖了过渡的所有基础。关键是要确保从“任何元素”到“隐藏”状态的“转换”是立即的,然后在从叠加层的“可见”到“隐藏”状态的情况下覆盖那个立即转换。
如果您正在开发自定义控件(而不是UserControl)并因此在控件模板中定义VisualStateManager,则上述方法(基于Loaded事件启动VisualState更改)将可能不起作用。这是因为在调用OnApplyTemplate()
覆盖之前,控件的可视树(在样式文件中定义)将被应用于您的控件,这通常是在第一个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);
}
}