在定义为静态资源的故事板上设置Storyboard.Targetname

时间:2013-08-08 14:24:44

标签: c# wpf storyboard staticresource

如果我将故事板定义为静态资源,例如:

<Storyboard
        x:Key="shakeAnimation"
    >
    <DoubleAnimationUsingKeyFrames
        Storyboard.TargetProperty="RenderTransform.X" 
        RepeatBehavior="5x"
        >
        <EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0"/>
        <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="3"/>
        <EasingDoubleKeyFrame KeyTime="0:0:0.15" Value="0"/>
        <EasingDoubleKeyFrame KeyTime="0:0:0.20" Value="-3"/>
        <EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="0"/>
    </DoubleAnimationUsingKeyFrames>

</Storyboard>

并想申请我可以做的地方

<MultiDataTrigger.EnterActions >
     <BeginStoryboard>
         <StaticResource  
                         ResourceKey="shakeAnimation"/>
    </BeginStoryboard>
 </MultiDataTrigger.EnterActions>

我认为它有效。但是,如果我想将动画应用于特定对象,那么这不起作用

<MultiDataTrigger.EnterActions >
     <BeginStoryboard>
         <StaticResource Storyboard.TargetName="editWidget"  
                         ResourceKey="shakeAnimation"/>
    </BeginStoryboard>
 </MultiDataTrigger.EnterActions>

因为我收到错误

  

附加属性“TargetName”只能应用于派生自“DependencyObject”的类型。

有没有一种简洁的方法将我的故事板存储为静态资源,并将它们应用于我想要的元素?

1 个答案:

答案 0 :(得分:3)

我认为您需要使用自定义附加属性来执行此操作。您将克隆Storyboard,并在克隆上设置TargetName并返回它。你的课程看起来像这样:

public static class NamedStoryboard
{
    public static readonly DependencyProperty StoryboardProperty = DependencyProperty.RegisterAttached(
      "Storyboard",
      typeof(Storyboard),
      typeof(NamedStoryboard),
      new FrameworkPropertyMetadata(DoAttach));

    [AttachedPropertyBrowsableForType(typeof(BeginStoryboard))]
    public static Storyboard GetStoryboard(BeginStoryboard obj)
    {
        return (Storyboard)obj.GetValue(StoryboardProperty);
    }

    public static void SetStoryboard(BeginStoryboard obj, Storyboard value)
    {
        obj.SetValue(StoryboardProperty, value);
    }

    public static readonly DependencyProperty TargetNameProperty = DependencyProperty.RegisterAttached(
      "TargetName",
      typeof(string),
      typeof(NamedStoryboard),
      new FrameworkPropertyMetadata(DoAttach));

    [AttachedPropertyBrowsableForType(typeof(BeginStoryboard))]
    public static string GetTargetName(BeginStoryboard obj)
    {
        return (string)obj.GetValue(TargetNameProperty);
    }

    public static void SetTargetName(BeginStoryboard obj, string value)
    {
        obj.SetValue(TargetNameProperty, value);
    } 

    private static void DoAttach(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var begin = d as BeginStoryboard;
        if (begin == null) return;

        var sb = GetStoryboard(begin);
        if (sb == null) return;

        var name = GetTargetName(begin);
        if (string.IsNullOrEmpty(name))
            begin.Storyboard = sb;
        else
        {
            var clone = sb.Clone();
            Storyboard.SetTargetName(clone, name);
            begin.Storyboard = clone;
        }
    }
}

你会这样使用它:

<BeginStoryboard local:NamedStoryboard.Storyboard="{StaticResource shakeAnimation}"
                 local:NamedStoryboard.TargetName="editWidget" />