WPF和MVVM:使用RotateTransform和DoubleAnimation沿圆形路径移动对象



我对WPF动画比较陌生。我想让一个物体(例如一个简单的圆(以10度的增量在圆形路径上移动。下面的例子非常接近:WPF圆形移动对象参见Clemens的答案,他在XAML中使用RotateTransform,在代码背后使用DoubleAnimation。然而,我正在使用MVVM,我不清楚如何实现这一点。我相信我需要从ViewModel访问视图中的RotateTransform,这样我就可以调用BeginAnimation,但如何调用呢?

有什么例子或想法吗?我找了半天都没找到。感谢

更新:我现在可以通过展示我已经尝试过的内容来更具体地回答我的问题。基于上述参考文献AND Twoway绑定视图';s视图模型的DependencyProperty';的财产?(由@Michael Schnerring回答(,我有以下简单的代码(如下(。我的椭圆没有旋转。没有绑定错误,或任何其他错误,只是没有旋转。我的方法被击中了(我调试到它中(我猜我的PerformAnimation函数不正确,特别是SetTargetProperty部分。我确实尝试过添加两个动画(一个用于旋转,一个用于变换(,但没有成功。

有人能告诉我我做错了什么吗?

XAML:

<Canvas Grid.Row="0" Grid.Column="0">
<Ellipse Height="100" Width="100" Fill="Aqua" Name="MyEllipse"
Canvas.Left="200" Canvas.Top="200"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<TranslateTransform Y="-100"/>
<RotateTransform />
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
<Button Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Command="{Binding Path=RotateCommand}">Press Me!</Button>

背后的代码

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var nameOfPropertyInVm = "AngleProperty";
var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay };
this.SetBinding(AngleProperty, binding);
}
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
// Using a DependencyProperty as the backing store for Angle.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(MainWindow), new UIPropertyMetadata(0.0, new PropertyChangedCallback(AngleChanged)));
private static void AngleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MainWindow control = (MainWindow)sender;
control.PerformAnimation((double)e.OldValue, (double)e.NewValue);
}
private void PerformAnimation(double oldValue, double newValue)
{
Storyboard s = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.From = oldValue;
animation.To = newValue;
animation.Duration = new Duration(TimeSpan.FromSeconds(1));
s.Children.Add(animation);

Storyboard.SetTarget(animation, MyEllipse);
Storyboard.SetTargetProperty(animation, new PropertyPath("(Ellipse.RenderTransform).(RotateTransform.Angle)"));
s.Begin();
}

和ViewModel

public class MyViewModel :  ViewModelBase
{
private ICommand _rotateCommand = null;
private double _angleProperty = 10;
public MyViewModel()
{

}
public double AngleProperty
{
get
{
return _angleProperty;
}
set
{
_angleProperty = value;
OnPropertyChanged("AngleProperty");
}
}
public ICommand RotateCommand
{
get
{
if (_rotateCommand == null)
{
_rotateCommand = new RelayCommand(param => RotateCommandImplementation());
}
return _rotateCommand;
}
}
private void RotateCommandImplementation()
{
AngleProperty = AngleProperty + 10;
}
}

这是我的解决方案,基于@Clemens的大量帮助(参见注释和WPF循环移动对象(

查看

<Window x:Class="AnimationBindingPlay.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AnimationBindingPlay"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Canvas Grid.Row="0" Grid.Column="0">
<Ellipse Height="100" Width="100" Fill="Aqua" Name="MyEllipse"
Canvas.Left="200" Canvas.Top="200"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<TranslateTransform Y="-100"/>
<RotateTransform x:Name="rotateTransform"/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
<Button Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Command="{Binding Path=RotateCommand}">Press Me!</Button>

</Grid>

背后的代码

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var nameOfPropertyInVm = "AngleProperty";
var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay };
this.SetBinding(AngleProperty, binding);
}
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
// Using a DependencyProperty as the backing store for Angle.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(MainWindow), new UIPropertyMetadata(0.0, new PropertyChangedCallback(AngleChanged)));
private static void AngleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MainWindow control = (MainWindow)sender;
control.PerformAnimation((double)e.OldValue, (double)e.NewValue);
}
private void PerformAnimation(double oldValue, double newValue)
{

var rotationAnimation = new DoubleAnimation(oldValue, newValue, TimeSpan.FromSeconds(1));
rotateTransform.BeginAnimation(RotateTransform.AngleProperty, rotationAnimation);
}
}

ViewModel和问题一样!

最新更新