开发者

Starting an animation from the ViewModel in WPF/MVVM

开发者 https://www.devze.com 2022-12-24 04:16 出处:网络
I\'m wr开发者_如何学Pythoniting a MVVM app and have started putting in a few animations. I want to call something on the ViewModel which starts the a storyboard. This blog had a promising approach to

I'm wr开发者_如何学Pythoniting a MVVM app and have started putting in a few animations. I want to call something on the ViewModel which starts the a storyboard. This blog had a promising approach to it, but it doesn't actually work. The IDChanged handler never fires for some reason.

I also found that you could start animations on EventTriggers, but I don't know how to raise one on the ViewModel.


I did this by a using DataTrigger and binding it to a property in my ViewModel. When the "FlashingBackGround" property gets set to "ON" the Storyboard animation starts.

Also make sure to include in your project a reference to "Microsoft.Expression.Interactions"

XAML: (this goes directly in the root node)

<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));
        }
    }

Finally, the Viewmodel must inherit from "INotifyPropertyChanged"


I ran into the same problem, and none of these posts really helped because the animations are in code, and some of them were large and complicated and required fluctuating variables so they had to stay in code. I resolved it by adding dependency properties in the user control (view) that trigger the animations, and binding them to properties in the view-model. Don't know (/care) if this violates something or other, because it works very well! cheers, stepp

excerpt:

(view) Usercontrol code behind:

    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

View-Model:

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


I have a property in my VM that reflects the state of the application. The elements in the view that are animated have a data trigger that starts a storyboard when the VM property has a certain value.


I ended up adding an AnimationStarted event to my ViewModel with a key string for what animation it is. Then on the view I create the animation programmatically, subscribe to the AnimationStarted event, and kick the appropriate animation off when it fires.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号