Wednesday, January 29, 2014

How to use DoubleAnimation in Windows Store Apps with C# without using XAML


I seem to find myself looking this up every time I go to create an animation, and since most of the example online use XAML, I wanted to write an easy to follow example to reference.
There is a great article on MSDN about using Animations in .NET 4.5 and it does provide a pure C# example.  However, there is a subtle difference in how you attach dependency properties for Windows Store / RT apps. 
http://msdn.microsoft.com/en-us/library/ms752312(v=vs.110).aspx

1st – you don’t need an object name when setting the Animation target.  You just need to pass the instance of the target.
.NET 4.5 –> StoryBoard.SetTarget(myDoubleAnimation, myTarget.Name);
Win8 Store –> StoryBoard.SetTarget(myDoubleAnimation, myTarget);
2nd – you reference the target animation property by name (ie a string) rather than creating a Property Path.  Basically they’ve just streamlined the process a bit.
Now onto the code.  I’ve placed everything into a single method with lazy loading, which isn’t likely how I would do it in production code, but it gets the job done.  As well, it shows how to add multiple DoubleAnimations to a single storyboard.  It’s straight forward but it seems to be a common question.  Note – we aren’t able to set multiple targets for one Animation.
Finally, the animation itself is a fun one to use, especially against a white background as objects appear to “flash” and then return to their original state.
I typically use this on custom UserControls but any UI object should work fine.
Here it is:
Storyboard storyPop;
DoubleAnimation dbAniX, dbAniY, dbAniFade;
public void FlashPop ()
{
    if (dbAniX == null)
    {
        ScaleTransform sTrans = new ScaleTransform() { ScaleX = 1.0, ScaleY = 1.0, CenterX = this.ActualWidth / 2, CenterY = this.ActualHeight / 2 };
        this.RenderTransform = sTrans;
 
        dbAniX = new DoubleAnimation() { From = 1.0, To = 2.0, Duration = TimeSpan.FromMilliseconds(100), AutoReverse = true };
        dbAniY = new DoubleAnimation() { From = 1.0, To = 2.0, Duration = TimeSpan.FromMilliseconds(100), AutoReverse = true };
        dbAniFade = new DoubleAnimation() { From = 1.0, To = 0.0, Duration = TimeSpan.FromMilliseconds(100), AutoReverse = true };
 
        Storyboard.SetTarget(dbAniX, sTrans);
        Storyboard.SetTarget(dbAniY, sTrans);
        Storyboard.SetTarget(dbAniFade, this);
 
        Storyboard.SetTargetProperty(dbAniY, "ScaleY");
        Storyboard.SetTargetProperty(dbAniX, "ScaleX");
        Storyboard.SetTargetProperty(dbAniFade, "Opacity");
    }
    
    if(storyPop == null)
    {
        storyPop = new Storyboard();
        storyPop.Children.Add(dbAniX);
        storyPop.Children.Add(dbAniY);
        storyPop.Children.Add(dbAniFade);
    }
 
    storyPop.Begin();
}