The way I handle this in my MVVM application is to bind the location of the rectangle to a ViewModel object. When that position is updated, the rectangle moves. I then have a behavior tied to the LayoutUpdated event of the rectangle itself that uses a translate transform to move the item back to its original location and then runs an animation over that translate transform to move the X and Y values down to 0, so the item animates to its "real" location.
<Border Width="{Binding PositionRectangle.Width}"
Height="{Binding PositionRectangle.Height}"
BorderBrush="{Binding OptionColorBrush}"
BorderThickness="3">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<ScaleTransform/>
</TransformGroup>
</Border.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger EventName="LayoutUpdated">
<ic:AnimationTriggerAction LocationPropertyName="Location"/>
</i:EventTrigger>
<i:EventTrigger EventName="Loaded">
<ic:AnimationTriggerAction LocationPropertyName="Location"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextWrapping="Wrap"/>
</Border>
The Trigger I am using (AnimationTriggerAction) was hand-rolled, since I wanted it to do a few other things as well (e.g. it handles running a scale animation over the item when it is first loaded as well, so it scales itself into existence), but nothing here is too difficult. It descends from TargetedTriggerAction<FrameworkElement>
and keeps track of the object's previous location in a dependency property on that item. It creates the storyboard if it doesn't exist and adds 2 DoubleAnimation
s to it to run over the X and Y properties of the TranslateTransform
.
Positive points to this approach:
No need to handle events in the .xaml.cs to fire up the animations. It all happens from the LayoutUpdated
and Loaded
events.
The fact that animations are occurring is entirely hidden from the ViewModel.
Negative points:
There is a slight flicker as the object snaps into existence and then the translate transform is set, so it snaps back to the original location before the animation starts. It's very subtle but it is there.
This isn't really ready for public consumption yet, but my proof of concept for this is located here: http://www.benvonhandorf.com/Apps/WOM/WheelOfMeat.html Enter an option name in the textbox and hit enter and you should see the option fade into existance. Enter a few more and you'll see them rearrange themselves around the wheel.