使用数据绑定在WPF中启动动画

9

我正在尝试将一个简单的WPF应用程序改为使用模型-视图-视图模型模式。在我的页面上,我有几个动画:

<Page.Resources>
    <Storyboard x:Name="storyboardRight"
                x:Key="storyboardRight">
        <DoubleAnimation x:Name="da3"
                         Storyboard.TargetName="labelRight"
                         Storyboard.TargetProperty="Opacity"
                         From="0"
                         To="1"
                         Duration="0:0:0.5" />
        <DoubleAnimation x:Name="da4"
                         Storyboard.TargetName="labelRight"
                         Storyboard.TargetProperty="Opacity"
                         From="1"
                         To="0"
                         BeginTime="0:0:1"
                         Duration="0:0:0.5" />
    </Storyboard>
    ...
</Page.Resources>

目前我在代码后台开始动画,并可以使用以下代码侦听完成事件,以便在完成时执行某些操作:

storyboardRight = (Storyboard)TryFindResource("storyboardRight");
storyboardRight.Completed += new EventHandler(storyboardRight_Completed);
storyboardRight.Begin(this);

有没有一种方法将故事板数据绑定到我的ViewModel,以便它在ViewModel引发的事件上启动,并在完成时回调到该ViewModel?
3个回答

8
我有机会向微软的Josh Twist提出了这个问题,他很友善地花时间回答了这个问题。解决方案是使用DataTrigger与ViewModel中的枚举相结合来启动Storyboard,这又需要将页面放入ContentPresenter中。为了处理动画完成,需要在代码后面加上一小段代码,以调用ViewModel中的ICommand。请阅读Josh的文章here,以获取完整的解决方案说明。

这个解决方案只需要将页面放入ContentPresenter中,如果您使用DataTemplate的话。如果您要对控件的属性进行动画处理,可以在控件自己的样式触发器中使用它,而不是DataTemplate的触发器。 - Nathan Phillips
Josh Twists网站的链接已经失效。显然,Josh的整个网站都出了问题(没有博客文章可以加载),当我尝试给他发送电子邮件时,它就会被退回。有人知道如何联系Josh并解决这个问题吗? - Simon Gillbee
@SimonGillbee 我已经在 Twitter 上给他发了一条消息。 - Mark Heath

2

我通过使用DataTrigger并将其绑定到ViewModel中的一个属性来实现这一点。当“FlashingBackGround”属性设置为“ON”时,Storyboard动画开始。

此外,请确保在您的项目中包含对“Microsoft.Expression.Interactions”的引用。

XAML:(直接放在根节点中)

<Window
   xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
   xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
   x:Name="window" >
    ...

    <i:Interaction.Triggers>
      <ei:DataTrigger Binding="{Binding FlashingBackground, Mode=OneWay}" Value="ON">
        <ei:ControlStoryboardAction Storyboard="{StaticResource MyAnimation}"     
                                                ControlStoryboardOption="Play"/>
      </ei:DataTrigger>
    </i:Interaction.Triggers>

    ...
</Window>

视图模型:

    private void TurnOnFlashingBackround()
    {
        this.FlashingBackground = "ON";
    }

    private string _FlashingBackround = "OFF";

    public string FlashingBackground
    {
        get { return this._FlashingBackround; }

        private set
        {
            if (this.FlashingBackground == value)
            {
                return;
            }

            this._FlashingBackround = value;
            this.OnPropertyChanged("FlashingBackground");
        }
    }

    public new event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(
                this, 
                new PropertyChangedEventArgs(propertyName));
        }
    }

最后,Viewmodel 必须继承 "INotifyPropertyChanged" 接口。


还要注意:您需要两个程序集引用:System.Windows.Interactivity 和上述提到的 Microsoft.Expression.Interactions。 - eFloh

1

1
谢谢你的指引,但是所有EventTrigger的文档都显示它是由现有FrameworkElement触发的事件触发的。我现在从我的ViewModel中触发了一个RoutedEvent,但不知道如何让XAML订阅它: <EventTrigger RoutedEvent="my:NumbersViewModel.RightAnswer"> - Mark Heath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接