I'm having difficulties animating a render transform of a Canvas object using a data trigger. As a test case I have an ellipse on a Canvas along with two buttons. When I press each button I want the position of the ellipse to animate to that button's X coordinate:
The fact that I'm using buttons in this particular example is neither here-nor-there, the point is I'm trying to trigger these animations with a DataTrigger bound to a property in my view model:
// this is the property my DataTrigger will bind to
private string _Anim;
public string Anim
{
get { return this._Anim; }
set
{
this._Anim = value;
RaisePropertyChanged(() => this.Anim);
}
}
// a command handler for the buttons that sets my animation property
public ICommand AnimCommand { get { return new RelayCommand<string>(OnAnim); } }
private void OnAnim(string value)
{
this.Anim = String.Empty; // cancel any existing animation, probably not needed...
this.Anim = value;
}
Here's the Xaml I'm using to do this. It's basically just a canvas containing an ellipse and two buttons, and the ellipse has 2 storyboards that get triggered in response to the backend property being set to different strings (i.e. "Left" and "Right"):
<Viewbox xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Canvas Width="350" Height="150" Background="CornflowerBlue">
<Ellipse x:Name="MyEllipse" Width="20" Height="20" Fill="Red">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="myTransform" X="50" Y="50" />
</Ellipse.RenderTransform>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Style.Triggers>
<DataTrigger Binding="{Binding Anim}" Value="Left">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="100" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Anim}" Value="Right">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="200" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Button x:Name="btnLeft" Content="Left" Command="{Binding AnimCommand}" CommandParameter="Left" Canvas.Left="100" Canvas.Top="100" Width="32" Height="24" />
<Button x:Name="btnRight" Content="Right" Command="{Binding AnimCommand}" CommandParameter="Right" Canvas.Left="200" Canvas.Top="100" Width="32" Height="24" />
</Canvas>
</Viewbox>
When I run this I can click on the first animation and then the second, and the behaviour is correct both times. However clicking on them in reverse order doesn't work...the "right" button animates correctly and the "left" button does nothing. It's as if the "right" animation is still running or locking down the property or something, a case further backed up by the fact that the situation is reversed if I swap the order of the storyboard declarations in the Xaml.
This works fine with EventTriggers, I'm only seeing it with DataTriggers. I've also tried playing with the FillBehaviours and HandoffBehaviors, to no avail. Can someone please explain why this is happening and how to fix it?

x:Nameto a BeginStoryboard element and remove it by RemoveStoryboard in an ExitAction. - Clemens