如何使元素引用XAML中的StaticResource Storyboard(而不是引用元素的storyboard)

时间:2013-04-23 14:02:50

标签: wpf xaml animation mvvm storyboard

我正在阅读MSDN动画教程,它描述了将故事板应用于元素的以下步骤:

  1. 创建故事板;
  2. 使用TargetName属性指定其目标元素名称;
  3. (指定目标属性);
  4. (添加事件触发器以启动动画);
  5. 我看到了一个概念问题,从中得出了我的困难,这就是:

      

    我在故事板和元素之间有一对一的关系,这种关系在故事板中定义。然后,我怎么能创建一个故事板,并有条件地将它应用于多个元素,从元素自身触发动画(通过Binding / Triggers,我猜)。

    我的预期用例是模仿一组LED(椭圆形的堆叠面板),其中每个LED可以处于以下四种逻辑状态之一:开,关,快速闪烁和慢速闪烁(非常像以太网路由器那样) 。然后,我创建动画BlinkingSlowBlinkingFast,然后在我的ViewModel进入相应的逻辑状态时触发。然后,我可以关注ViewModel中的行为,并让View自行处理,并正确触发并重用一些StaticResource Storyboard。

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:System="clr-namespace:System;assembly=mscorlib"
            xmlns:local="clr-namespace:blinking"
            x:Class="blinking.MainWindow"
            Title="MainWindow"
            Background="{x:Null}"
            WindowStartupLocation="CenterScreen">
    
        <Window.Resources>
            <System:Double x:Key="Diameter">40</System:Double>
            <Color x:Key="RedOn">Red</Color>
            <Color x:Key="RedOff">#FF570000</Color>
            <Storyboard x:Key="BlinkSlow" RepeatBehavior="Forever">
                <ColorAnimationUsingKeyFrames
                        Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                        Storyboard.TargetName="led4"
                        AutoReverse="True"
                        RepeatBehavior="Forever">
                    <DiscreteColorKeyFrame KeyTime="0" Value="{StaticResource RedOn}"/>
                    <DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="{StaticResource RedOn}"/>
                    <EasingColorKeyFrame KeyTime="0:0:0.5" Value="{StaticResource RedOff}"/>
                    <DiscreteColorKeyFrame KeyTime="0:0:1" Value="{StaticResource RedOff}"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>       
        </Window.Resources>
    
        <Window.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                <BeginStoryboard Storyboard="{StaticResource BlinkSlow}"/>
            </EventTrigger>
        </Window.Triggers>
    
        <StackPanel x:Name="leds_container" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,4,0">
            <Ellipse x:Name="led1" Width="{StaticResource Diameter}" Height="{StaticResource Diameter}" Fill="#FFF90F0F" Margin="20,0,0,0"/>
            <Ellipse x:Name="led2" Width="{StaticResource Diameter}" Height="{StaticResource Diameter}" Fill="#FFF90F0F" Margin="20,0,0,0"/>
            <Ellipse x:Name="led3" Width="{StaticResource Diameter}" Height="{StaticResource Diameter}" Fill="#FFF90F0F" Margin="20,0,0,0"/>
            <Ellipse x:Name="led4" Width="{StaticResource Diameter}" Height="{StaticResource Diameter}" Fill="#FFF90F0F" Margin="20,0,0,0"/>
        </StackPanel>
    </Window>
    

    有什么建议吗?

1 个答案:

答案 0 :(得分:3)

你可以使用Style-Triggers。

在参考资料部分创建故事板,就像您已经做过的那样,但没有目标名称。

然后为椭圆创建一个包含DataTrigger的样式,启动当前状态所需的动画。

例如:

<Window.Resources>
    <!--
    Other declarations
    -->
    <Style TargetType="{x:Type Ellipse}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=State, Mode=OneWay}" Value="BlinkSlow">
                <DataTrigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource BlinkSlow}" />
                </DataTrigger.EnterActions>
            </DataTrigger>
            <!--
            Add DataTrigger for your other states too.
            -->
        </Style.Triggers>
    </Style>
</Window.Resources>