多个目标名称的相同动画

时间:2010-02-12 10:34:25

标签: wpf image animation

只是一个疑问。我的WPF应用程序中有三个图像。我将为这三个图像提供眨眼效果。所以我给了这个代码。

<Storyboard x:Key ="AlarmBlink">
       <DoubleAnimation
            Storyboard.TargetName="Img1"
            Storyboard.TargetProperty="Opacity"
      From="1" To="0" Duration="0:0:0.1" 
      AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>

这个是FirstImage(Img1)。所以我必须给出其他两个图像。我可以在previus编码中给出多个taget名称。 否则,我必须复制并粘贴相同的编码和更改目标名称。 有没有办法让单一编码?

3 个答案:

答案 0 :(得分:2)

你不能在DoubleAnimation中放置多个Storyboard.TargetNames,但有一种更好的方法:使用数据绑定将三个Opacity值绑定在一起,然后只为其中一个设置动画,其他的也会改变。

注意:为避免在创建绑定时出现不对称,您可能需要使用此额外的技术:

  1. 使用Visibility =“Collapsed”创建第四个控件,以便您永远不会看到它
  2. 为此控件的不透明度设置动画
  3. 将所有三个可见控件的不透明度绑定到不可见控件的不透明度。
  4. 另一种选择是使用单个DoubleAnimation并使用后面的代码将其应用于所有三个图像,而不是使用WPF的StoryBoard机制。这为您提供了更多控制权,但需要您编写代码隐藏。

    一般来说,我坚持使用绑定解决方案,因为它最简单。在任何情况下,剪切和粘贴解决方案通常都是最糟糕的。

答案 1 :(得分:0)

1.为StaticResource定义DoubleAnimation。 (因为你不能将故事板用于多个元素):

<Window.Resources>
   <DoubleAnimation x:Key="DA"
        Storyboard.TargetName="Img1"
        Storyboard.TargetProperty="Opacity"
        From="1" To="0" Duration="0:0:0.1" 
        AutoReverse="True" RepeatBehavior="Forever" />
</Window.Resources> 

2.对您的元素使用此资源,并使用Storyboard.TargetName定义RelativeSource Binding。例如:

<Image Name="img1">
      <Image.Triggers>
           <EventTrigger RoutedEvent="Image.Loaded">
                <BeginStoryboard  >
                    <Storyboard Storyboard.TargetName="{Binding Name,RelativeSource={RelativeSource AncestorType=Image,Mode=FindAncestor}}">
                        <StaticResourceExtension ResourceKey="DA" />
                    </Storyboard>
                </BeginStoryboard>
           </EventTrigger>
       </Image.Triggers>
 </Image>

答案 2 :(得分:0)

您可以创建一个可重用的附加属性,该属性可以附加到从UIElement派生的任何控件上(因为这是在最低级别定义属性Opacity的地方),例如:

public class OpacityAnimation
{
    public static readonly DependencyProperty IsEnabledProperty = 
        DependencyProperty.RegisterAttached(
          "IsEnabled", typeof(bool), typeof(OpacityAnimation), new FrameworkPropertyMetadata(false, 
          FrameworkPropertyMetadataOptions.AffectsRender, IsEnabledChanged));

    public static void SetIsEnabled(DependencyObject element, bool value)
    {
        element.SetValue(IsEnabledProperty, value);
    }

    public static bool GetIsEnabled(DependencyObject element)
    {
        return (bool)element.GetValue(IsEnabledProperty);
    }

    private static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is UIElement uiElement))
            throw new Exception("DependencyObject has to be of type UIElement");

        if (e.NewValue is bool isEnabled && isEnabled)
        {
            var doubleAnimation = CreateAnimation(500);
            uiElement.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);
        }
        else
        {
            uiElement.BeginAnimation(UIElement.OpacityProperty, null);
        }
    }

    private static AnimationTimeline CreateAnimation(int durationMs)
    {
        return new DoubleAnimation
        {
            FillBehavior = FillBehavior.Stop,
            RepeatBehavior = RepeatBehavior.Forever,
            AutoReverse = true,
            Duration = new Duration(TimeSpan.FromMilliseconds(durationMs)),
            From = 0,
            To = 1
        };
    }
}

在项目中的任何地方创建此类。

然后使用它:(记住要在XAML中引用您的名称空间)

<Path attachedProperties:OpacityAnimation.IsEnabled="{Binding IsBlinking}"
      Data="M 0,0 L 0,50 L 50,50 L 50,0" Fill="Red"/>

这样,您可以将其附加到您喜欢的任何属性,并将IsEnabled绑定到ViewModel属性以控制动画。对于这样的简单动画,您甚至不需要情节提要。

附加属性是WPF的一项奇妙功能!