为多个VisualStateGroup实现VisualStates的正确方法是什么?

时间:2014-09-12 16:18:08

标签: c# wpf xaml visualstatemanager visualstates

此问题是my previous question以及this related question关于VisualStates如何在WPF中工作的后续行动。

目前,我的理解是在不同VisualStateGroups内动画相同属性可能会导致问题(请参阅相关问题)。

要解决这些问题,需要利用循环漏洞。 (也许loop-hole不是正确的术语,但似乎解决方案不是WPF设计者的意图。)

我想知道在多个VisualStateGroups中动画相同属性的正确方法是什么,而不会产生不良副作用。如果不可能,那么为控件实现相同视觉行为的正确途径是什么?

我能够在MSDN找到一些相关文档:

  

控件始终处于每组的一个状态。例如,即使鼠标指针没有在按钮上,按钮也可以有焦点,因此处于聚焦状态的按钮可以处于MouseOver,Pressed或Normal状态。

这引出了我的第二个问题......

您如何提供仅在两个特定VisualStates处于活动状态时才会出现的视觉行为?

ToggleButton

为例
  • 如果按钮已选中,我想显示行为1
  • 如果按钮已禁用,我想显示行为2
  • 最后,如果按钮已检查已禁用,我想显示行为3

在上面的例子中,你将如何渲染第三个视觉行为?

1 个答案:

答案 0 :(得分:3)

对于问题的第一部分,您希望每个状态与每个状态的不同单个对象进行交互,而不是与每个VisualState匹配相同的对象,例如;

    <VisualState x:Name="Disabled">
      <Storyboard>
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledState" 
                                  Storyboard.TargetProperty="(UIElement.Visibility)">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
          </ObjectAnimationUsingKeyFrames>
       </Storyboard>
    </VisualState>
    <VisualState x:Name="Checked">
      <Storyboard>
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckedState" 
                                  Storyboard.TargetProperty="(UIElement.Visibility)">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
          </ObjectAnimationUsingKeyFrames>
       </Storyboard>
    </VisualState>

<!-- Each state interacts with its own object in your ControlTemplate ideally -->
<Border x:Name="CheckedState" Visibility="Collapsed"
        Background="Green"/>
<Border x:Name="DisabledState" Visibility="Collapsed"
        Background="White" Opacity=".5"/>

而不是一个对象共享属性更改,如;

<VisualState x:Name="Disabled">
  <Storyboard>
      <ColorAnimation d:IsOptimized="True"
                      Duration="0"
                      Storyboard.TargetName="Background"
                      Storyboard.TargetProperty="(SolidColorBrush.Color)"
                      To="White" />
   </Storyboard>
</VisualState>
<VisualState x:Name="Checked">
  <Storyboard>
      <ColorAnimation d:IsOptimized="True"
                      Duration="0"
                      Storyboard.TargetName="Background"
                      Storyboard.TargetProperty="(SolidColorBrush.Color)"
                      To="Green" />
   </Storyboard>
</VisualState>

<Border x:Name="Background" Background="Blue"/>

根据你的第二个问题,A VisualState将作为一个bool,因为它既是,也不是在那个状态。要分享一个州的声明,你必须在某个地方或某个地方添加一个MultiTrigger或转换器更多的技巧。

希望这会有所帮助。干杯

编辑添加:

所以你也可以VisualTransition使用你可以使用的;

 <VisualStateManager.VisualStateGroups>
  <VisualStateGroup x:Name="CommonStates">
    <VisualStateGroup.Transitions>
      <VisualTransition From="Normal"
        GeneratedDuration="0:0:0.2"
        To="Checked">
        <VisualTransition.GeneratedEasingFunction>
          <ExponentialEase EasingMode="EaseIn" Exponent="7" />
        </VisualTransition.GeneratedEasingFunction>
      </VisualTransition>
      <VisualTransition From="Checked"
        GeneratedDuration="0:0:0.2"
        To="Normal">
        <VisualTransition.GeneratedEasingFunction>
          <CircleEase EasingMode="EaseIn" />
        </VisualTransition.GeneratedEasingFunction>
      </VisualTransition>
    </VisualStateGroup.Transitions>
    <VisualState x:Name="Normal" />
    <!-- etc, etc, etc -->

因此,您可以使用不同的缓动,生成的持续时间等等。