【问题标题】:How to make an element reference a StaticResource Storyboard in XAML (instead of the storyboard referencing the element)如何使元素引用 XAML 中的 StaticResource 故事板(而不是引用元素的故事板)
【发布时间】:2013-04-16 18:57:40
【问题描述】:

我正在阅读 MSDN 动画教程,它描述了将情节提要应用于元素的以下步骤:

  1. 创建故事板;
  2. 使用TargetName 属性指定其目标元素名称;
  3. (指定目标属性);
  4. (添加事件触发器启动动画);

我看到了一个概念问题,我的困难由此而来,就是这样:

我在故事板和元素之间有一对一的关系,这种关系在故事板中定义。那么,我如何创建一个故事板,并有条件地将其应用于多个元素,从元素本身触发动画(我想是通过绑定/触发器)。

我的预期用例是模仿一个 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>

有什么建议吗?

【问题讨论】:

    标签: wpf xaml animation mvvm storyboard


    【解决方案1】:

    您可以为此使用样式触发器。

    像之前一样在资源部分创建故事板,但没有目标名称。

    然后为包含 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>
    

    【讨论】:

    • 试试吧,看来是个不错的解决方案,有新信息我会尽快反馈,谢谢!
    • 您介意建议我应该如何实现我的 ViewModel(用作 DataContext)吗?假设我有我的 LedsPanelViewModel,有一个名为“State”的属性,我应该如何设置这个属性?例如,使用像 this.State = "BlinkSlowState" 这样的字符串,或者我应该创建一个枚举?我很困惑...
    • 我做到了,它使用 Value 属性作为字符串。非常感谢!!
    • 你也可以使用枚举。它会起作用,因为它在内部作为整数处理。它将提高代码的可读性,您绝对应该使用 Enum。
    猜你喜欢
    • 1970-01-01
    • 2016-11-30
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2014-09-28
    • 2013-11-16
    • 1970-01-01
    相关资源
    最近更新 更多