从WPF/MVVM的ViewModel启动动画

12
我正在编写一个MVVM应用程序,并开始添加一些动画效果。我希望在ViewModel上调用某个东西来启动故事板。这篇博客提供了一个有希望的方法,但它实际上并不起作用。IDChanged处理程序出现了某些问题,不能正常触发。
我还发现可以在EventTriggers上启动动画,但不知道如何在ViewModel上引发EventTrigger。
4个回答

15

我通过使用DataTrigger将其绑定到ViewModel中的属性来实现此操作。当“FlashingBackGround”属性设置为“ON”时,故事板动画会启动。

还要确保在项目中包含对“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>

视图模型(ViewModel):

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

    private string _FlashingBackround = "OFF";

    public string FlashingBackground
    {
        get { return _FlashingBackround; }

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

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


10
有趣的方法。但为什么不使用布尔值而是使用“ON” /“OFF”字符串? - Isak Savo
请确保也添加了 "System.Windows.Interactivity.dll"。 - Benzara Tahar

3
我遇到了同样的问题,这些帖子都没有真正帮到我,因为动画是在代码中实现的,其中一些动画又非常庞大和复杂,需要使用波动变量,所以它们必须保留在代码中。我通过在用户控件(view)中添加依赖属性来触发动画,并将它们绑定到视图模型中的属性,从而解决了这个问题。不知道是否违反了什么规定,但它运行得非常好!祝好,stepp。
摘录: (view)用户控件代码后台:
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        SetAnimationBindings();
    }

    private void SetAnimationBindings()
    {
        _dialogStartPosition = mbFolderBrowse.Margin;

        var propName = "StartDialogAnimation";
        var binding = new Binding(propName) { Mode = BindingMode.TwoWay };
        this.SetBinding(DialogAnimationProperty, binding);

        propName = "StartProgressAnimation";
        binding = new Binding(propName) { Mode = BindingMode.TwoWay };
        this.SetBinding(ProgressAnimationProperty, binding);
    }

    #region Animation Properties
    #region DialogAnimation
    public static readonly DependencyProperty DialogAnimationProperty = 
        DependencyProperty.Register("DialogAnimation", typeof(bool),
            typeof(Manage), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDialogAnimationChanged));
    public bool DialogAnimation
    {

        get { return (bool)this.GetValue(DialogAnimationProperty); }
        set
        {
            var oldValue = (bool)this.GetValue(DialogAnimationProperty);
            if (oldValue != value) this.SetValue(DialogAnimationProperty, value);
        }
    }

    private static void OnDialogAnimationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        Manage m = o as Manage;

        if ((bool)e.NewValue == true)
            m.SlideInDialogPanel(); // animations
        else
            m.SlideOutDialogPanel();
    }
    #endregion

视图模型:

public bool StartDialogAnimation
{
    get { return _startDialogAnimation; }
    set
    {
        if (_startDialogAnimation != value)
        {
            _startDialogAnimation = value;
            RaisePropertyChanged("StartDialogAnimation");
        }
    }
}

2

我在虚拟机中有一个属性,反映了应用程序的状态。视图中被动画处理的元素具有数据触发器,当虚拟机属性具有特定值时,启动故事板。


我知道如何做。你可以设置一个触发器,在进入条件时启动故事板。但我只需要做一次性动画:我想在 UI 元素上快速、临时地闪烁,以引起注意。 - RandomEngy
我还没有考虑到通用化,所以我不知道这是否对你有帮助。我曾经有过类似的需求。如果一分钟内没有任何活动,我必须“闪烁”一个按钮。我通过将故事板附加到按钮上来实现这一点,故事板在一分钟内什么也不做,然后进行闪烁。在我的情况下,当点击按钮时,按钮消失了,因此情景更简单了。在UI元素上闪烁以吸引注意力听起来只与视图相关。视图是否可以自行确定何时进行闪烁?为什么VM要关心闪烁UI元素?抱歉,这可能没有太大帮助。 - Carlos
好的,多个命令在一个窗口上触发时会导致另一个窗口闪烁。我的窗口模型设置使得虚拟机知道窗口之间的关系,但视图不知道。 - RandomEngy
你有这个DataTrigger的一些示例代码吗?我尝试过了,但它并没有真正与我的DataBindings配合起来。 - Tigraine
@Tigraine - 我有一个示例,使用模型项的文本值。 - Ritch Melton

2

最终,我在我的ViewModel中添加了一个AnimationStarted事件,并使用键字符串指定了它所代表的动画。然后,在视图中,我通过编程方式创建了动画,订阅了AnimationStarted事件,并在其触发时启动相应的动画。


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