当绑定值更改时,启动动画的最佳方法是什么?

Ser*_*hov 7 data-binding wpf animation mvvm storyboard

这种情况经常出现:

在视图中,您有一个绑定到ViewModel属性的控件(由INotifyPropertyChanged支持).例如:

<TextBlock Text="{Binding Path=Subtotal}"/>
Run Code Online (Sandbox Code Playgroud)

当属性发生变化时,您需要通过一些创意动画吸引用户注意这一事实.我如何利用视图已连接到通知并避免创建大量额外代码(或至少创建一次并重复使用)这一事实.数据触发器可能是最好的选择,但我不知道如何使它们在任何值变化时触发,而不是某些特定值.

我想到以下选项:

  • 在ViewModel中引发一个额外的事件,在View代码隐藏中订阅.
  • 使用转换器创建绑定到提到的属性的数据触发器,如果​​值正在更改,则返回true.
  • 创建一个绑定到ViewModel上的新布尔属性的数据触发器,用于"发出信号"更改.
  • 创建一个附加到控件的行为,该行为将订阅控件的依赖项属性更改并启动动画.

你喜欢/使用哪一个?我错过了任何选择吗?

PS如果解决方案提供了首先启动动画并在结束时反映值变化的可能性,那将是很好的(但不是关键).

Ser*_*hov 3

好吧,这是我经过一番实验后得出的结论。

我创建了一个带有依赖属性的 Expression Blend 3 触发器(我将其命名为 Subscription)。我将订阅绑定到与 TextBlock 绑定的相同值,并将此触发器附加到 Expression Blend 3 中的 ControlStoryboardAction。

这是触发器:

public class DataTriggerPlus : TriggerBase<DependencyObject>
{
    public static readonly DependencyProperty SubscriptionProperty =
        DependencyProperty.Register("Subscription", 
            typeof(string),
            typeof(DataTriggerPlus),
            new FrameworkPropertyMetadata("",
              new PropertyChangedCallback(OnSubscriptionChanged)));

    public string Subscription
    {
        get { return (string)GetValue(SubscriptionProperty); }
        set { SetValue(SubscriptionProperty, value); }
    }

    private static void OnSubscriptionChanged(DependencyObject d,
      DependencyPropertyChangedEventArgs e)
    {
        ((DataTriggerPlus)d).InvokeActions(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是它附加到故事板的方式:

<TextBlock x:Name="textBlock" Text="{Binding TestProp}" Background="White">
    <i:Interaction.Triggers>
        <local:DataTriggerPlus Subscription="{Binding TestProp}">
            <im:ControlStoryboardAction 
                Storyboard="{StaticResource Storyboard1}"/>
        </local:DataTriggerPlus>
    </i:Interaction.Triggers>
</TextBlock>
Run Code Online (Sandbox Code Playgroud)

我非常喜欢这种方法,Blend 3 设计师干得好!

编辑:回答德鲁评论...

是的,它随 Blend 一起提供。您只需将 Microsoft.Expression.Interactions.dll 和 System.Windows.Interactivity 包含到您的项目中即可。

是的,它很冗长(我问过是否有人在这个问题中找到了通过样式应用行为的好方法) - 但灵活性也有一个好处。例如,您不仅可以启动故事板,还可以从同一触发器切换状态或执行其他操作。