如何在WPF中将绑定的属性值从旧值平滑过渡到新值

时间:2019-03-06 20:40:24

标签: wpf xaml

如何将绑定属性的先前值平滑地动画化为新值?

假设我们有以下“画布和线条”。

<Canvas>
    <Line 
        Canvas.Top="0"
        Stroke="#887FFF00"
        StrokeThickness="2"
        X1="0" Y1="0"
        X2="0" Y2="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Canvas}}"
        Canvas.Left="{Binding Position}"
        >
    </Line>
</Canvas>

线的水平位置由绑定到Canvas.Left附加属性的Position属性确定。当“位置”从100变为200时,我想使线条的位置从其先前的值动画化,平滑地变为其新值。

我该怎么做?

2 个答案:

答案 0 :(得分:0)

到目前为止,在wpf中平滑设置属性动画的最简单方法是使用动画。

不过,您的动画需要一些技巧。

您不能在动画上绑定“从”或“到”,这将涉及在代码中创建动画。

您需要一个依赖项属性,因此需要一个依赖项对象来为值设置动画。

您可以考虑制作将位置公开到依赖对象中的viewmodel。然后,您可以在需要动画的时候在代码中创建一个新的动画,只需在其中保留绑定即可。

或者...您可以将情节提要板定义为资源,并在代码中对其进行更改以制作动画。

喜欢这个https://social.technet.microsoft.com/wiki/contents/articles/31191.wpf-tips-animating-a-viewmodel.aspx

也许您不希望将viewmodel成为依赖对象。

如果您认为视图中有一些“代码落后”的意思,那就是一个依赖对象。您也可以在窗口中添加依赖项属性。将其绑定到“位置”,然后为该行或绑定到该行的另一个依赖项属性的canvas.left设置动画。

答案 1 :(得分:0)

您可以在视图中自己订阅视图模型的{Binding}事件,并通过编程为该属性设置动画,而不是使用XAML中的PropertyChanged语法直接绑定到源属性。 / p>

private void OnViewLoaded(object sender, RoutedEventArgs e)
{
    ViewModel viewModel = DataContext as ViewModel;
    if (viewModel != null)
    {
        Canvas.SetLeft(line, viewModel.Position);
        viewModel.PropertyChanged += OnPropertyChanged;
    }
}

private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Position")
    {
        double from = Canvas.GetLeft(line);
        if (double.IsNaN(from))
            from = 0;
        ViewModel viewModel = sender as ViewModel;
        if (viewModel != null)
        {
            DoubleAnimation doubleAnimation = new DoubleAnimation()
            {
                From = from,
                To = viewModel.Position,
                Duration = TimeSpan.FromSeconds(1)
            };
            line.BeginAnimation(Canvas.LeftProperty, doubleAnimation);
        }
    }
}

XAML:

<Canvas Width="100" Height="100" Background="Beige">
<Line x:Name="line"
        Canvas.Top="0"
        Stroke="#887FFF00"
        StrokeThickness="2"
        X1="0" Y1="0"
        X2="0" Y2="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Canvas}}">
</Line>
</Canvas>

这是您要在视图中实现自定义特定于视图的逻辑的情况的示例,并且您不想在XAML中执行此操作。这不会以任何方式破坏MVVM模式。