I'm relatively new to WPF animations. I would like to have an object (a simple circle for example) move around a circular path in 10 degree increments. The following example is tantalizingly close: WPF circular moving object See the answer by Clemens who uses a RotateTransform in XAML and a DoubleAnimation in code-behind. I am however, using MVVM and it's not clear to me how to accomplish this. I believe I would need to access the RotateTransform which is in the View from my ViewModel, so I can call BeginAnimation, but how?
Any examples or ideas? I have searched without luck. Thanks
UPDATE: I can now be more specific in my question by showing what I've already tried. Based on the above mentioned reference AND Twoway-bind view's DependencyProperty to viewmodel's property? (answer by @Michael Schnerring), I have the following simple code (below). My ellipse is not rotating. No binding errors, or any other errors, just no rotation. And my methods are hit (I debugged into it) I'm guessing my PerformAnimation function is incorrect, specifically the SetTargetProperty part. I did try to play with it by adding two animations (one for Rotation, one for Transform) but without luck.
Can someone give me an idea what I'm doing wrong?
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>
Code-behind
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();
}
And 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;
}
}