7

这是经常出现的情况:

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

<TextBlock Text="{Binding Path=Subtotal}"/>

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

想到以下选项:

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

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

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

4

2 回答 2

3

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

我创建了一个带有依赖属性的 Expression Blend 3 触发器(我将其命名为 Subscription)。我将 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);
    }
}

以下是它与情节提要的连接方式:

<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>

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

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

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

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

于 2009-07-14T18:26:36.040 回答
2

您可以创建一个触发器来启动动画。

像这样的东西:

<Style>
    <Style.Triggers>
       <Trigger 
            Property="ViewModelProperty"
            Value="True">
            <Trigger.EnterActions>
                 <BeginStoryboard Storyboard="YourStoryBoard" />
            </Trigger.EnterActions>
       </Trigger>
    </Style.Triggers>
</Style>

至于动画完成后设置值的问题,这有点痛苦。据我所知,您需要在情节提要上使用已完成的事件,这需要后面的代码,这是您希望使用 MVVM 避免的事情。

我尝试使用 EventTriggers 绑定到已完成的事件,但这也引入了一些复杂性。有关更多详细信息,请参见此处

于 2009-07-13T23:41:22.947 回答