为什么绑定不适用于动画? [英] Why bindings don't work with animations?

查看:50
本文介绍了为什么绑定不适用于动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对动画绑定属性有一个简单的问题.这是一个简单的示例来说明它:

I have a simple problem with an animated binded property. Here is a simple example to illustrate it :

ViewModel:

public class ViewModel
{

    private double myProperty;

    public double MyProperty
    {
        get { return myProperty; }
        set { myProperty = value; /* Break point here */ }
    }

    public ViewModel()
    {
        MyProperty = 20;
    }

}

MyControl:

public class MyControl : Button
{

    protected override void OnClick()
    {
        base.OnClick();
        Height = ActualHeight + 20;
    }

}

MyAnimatedControl:

public class MyAnimatedControl : Button
{

    protected override void OnClick()
    {
        base.OnClick();
        DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
        this.BeginAnimation(HeightProperty, a);
    }

}

MainWindow:

public partial class MainWindow : Window
{

    public MainWindow()
    {
        DataContext = new ViewModel();
        InitializeComponent();
    }
}

<Grid>
    <StackPanel>
        <local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
        <local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
        <local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
    </StackPanel>
</Grid>

我有两个控件是从

I have two controls inherited from Button (MyControl and MyAnimatedControl), their Height property is binded (mode two way) to the MyProperty property in the ViewModel.

单击控件时,它们会增大其Height属性.MyControl为它分配一个新值,然后MyAnimatedControl为它设置动画.

When the controls are clicked, they grow their Height property. The MyControl assigns it a new value and the MyAnimatedControl animates it.

问题:

当我单击MyControl之一时,绑定正常工作,所有控件的高度都已更新,断点在ViewModel中工作.但是,当我单击MyAnimatedControl时,绑定似乎不再起作用:它单独增长,并且绑定不再起作用,而两个常规控件仍一起增长.它不再与其他控件共享相同的高度.

When I click one of the MyControl, the bindings work correctly, all the controls' heights are updated, the break point works in the ViewModel. But when I click the MyAnimatedControl, the binding seems to not work anymore : it grows alone and the binding doesn't work anymore whereas the two normal controls still grow together. It doesn't share the same height with to other controls anymore.

是否可以对动画依赖项属性进行操作绑定,从而在整个动画过程中更新ViewModel?我阅读了这篇文章,但没有回答.

Is there a way to have an operational binding on an animated dependency property, which will update the ViewModel all along the animation? I read this post but it doesn't answer it.

谢谢.

推荐答案

问题似乎是动画属性同时是绑定的来源.为了解决这个问题,您可以创建另一个height属性(例如 MyHeight ),该属性在控件的高度发生变化时会更新,并用作 OneWayToSource 绑定的目标.

The problem seems to be that the animated property is at the same time the source of the binding. To get around this, you could create another height property (e.g. MyHeight) that gets updated whenever the control's height changes and that serves as the target of a OneWayToSource binding.

public class MyAnimatedControl : Button
{
    public static readonly DependencyProperty MyHeightProperty =
        DependencyProperty.Register(
            "MyHeight", typeof(double), typeof(MyAnimatedControl));

    public double MyHeight
    {
        get { return (double)GetValue(MyHeightProperty); }
        set { SetValue(MyHeightProperty, value); }
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        MyHeight = sizeInfo.NewSize.Height;
    }
}

绑定:

<local:MyAnimatedControl ...
   MyHeight="{Binding MyProperty, Mode=OneWayToSource}"
   Height="{Binding MyProperty, Mode=OneWay}"/>


为了更新其他绑定目标,您还需要在视图模型中实现 INotifyPropertyChanged 接口:

public class ViewModel : INotifyPropertyChanged
{
    private double myProperty = 30;
    public double MyProperty
    {
        get { return myProperty; }
        set
        {
            myProperty = value;
            RaisePropertyChanged("MyProperty");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


最后,正如Rohit Vats在他的答案中所写的那样,您需要删除Completed事件处理程序内Height属性上的动画保留:


Finally, as Rohit Vats has written in his answer, you'll need to remove the hold of the animation on the Height property inside the Completed event handler:

protected override void OnClick()
{
    base.OnClick();
    DoubleAnimation a = new DoubleAnimation(ActualHeight + 20,
                            new Duration(TimeSpan.FromMilliseconds(500)));
    a.Completed += (s, e) =>
    {
        BeginAnimation(Button.HeightProperty, null); // Remove animation.
        SetCurrentValue(Button.HeightProperty, ActualHeight); // Set value.
    };
    this.BeginAnimation(Button.HeightProperty, a);
}

这篇关于为什么绑定不适用于动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆