Animation in XAML (Part 1)

Introduction

I recently wrote a little application in WPF, which displayed a button. I thought it would be nice to have the button “burst” onto the screen, which is unlike me… normally the screen looks like it looks, or it looks like a command prompt (apparently not everything can be a console app).

When looking around on the web, I found very little information about this. What I did find was a mixture of code that didn’t work, wasn’t explained, or both. As you may have gathered from the previous paragraph; I’m no expert in this, but I’m going to try and collate my findings into a series of posts.

Button Animation using WPF with no code-behind

So here’s the code for creating a button in WPF (you might want to sit down, as the technical brilliance of this XAML may make you dizzy):

             <Button Width ="200" Height="150" name="testbutton">
                Don't Click Me               
            </Button>

I know, and still no call from Microsoft to go there as a consultant! Anyway, believe it or not, there’s more. I want to make the button expand as it’s loaded; so an event trigger allows me to do this quite easily (this is inside the button definition):

    <Button.Triggers>
        <EventTrigger RoutedEvent ="Button.Loaded">

So, anything in this event should fire when the button is loaded. What I want to fire is an animation. In WPF terms, this is a storyboard; basically, that’s just a collection of animations. The storyboard definition is inside the trigger:

<BeginStoryboard>
     <Storyboard>

The expanding animation looks something like this:

                                
                                <DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                                     From="0" To ="1" Duration="0:0:0.2"/>
                                <DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                                     From="0" To ="1" Duration="0:0:0.2"/>;
  

So what have I told it there? I’ve told it that I want to animate a double value (i.e. a floating point number) – DoubleAnimation; I’ve told it that I want to change a property within something called “MyAnimatedScaleTranform” (more on this in a minute); and that the property is called “ScaleTransform.ScaleX” (“ScaleTransform.ScaleY” for the second one). I’ve then told it what to change that property from and to, and how long to take.

Okay, so we now have a button, a storyboard and an animation that tells it what to do; but that’s not all – remember MyAnimatedScaleTranform from the last paragraph? The problem is that WPF doesn’t know what ScaleTransform is, and so inside the button definition we need to define that. Here’s the full code for the button:

<Button
  Name="testbutton"
  Width="200" Height="150">
    Don't Click Me               
    <Button.RenderTransform>                    
        <ScaleTransform x :Name="MyAnimatedScaleTransform"
              ScaleX="1" ScaleY ="1" CenterX="100" CenterY="75"  />
    </Button.RenderTransform>                
    <Button.Triggers>
        <EventTrigger RoutedEvent ="Button.Loaded">
             <BeginStoryboard>
                 <Storyboard>
                     <DoubleAnimation
                         Storyboard.TargetName="MyAnimatedScaleTransform"
                         Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                         From="0" To ="1" Duration="0:0:0.2"/>
                     <DoubleAnimation
                         Storyboard.TargetName="MyAnimatedScaleTransform"
                         Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                         From="0" To ="1" Duration="0:0:0.2"/>
                 </Storyboard>
             </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

The CentreX and CentreY properties tell it where to grow from (i.e. where the origin is). These values are relative, so you can place this button anywhere on a form and it will still grow from the middle.

So, that should do it… well, it should give you a button that grows into existence; try it. I wanted mine to “pop”, though. So I decided I needed it top grow a bit to big, and then correct itself. To make the button grow too big is easy-peasy:

From ="0" To ="1.2"

Now it grows too big. So it needs to get smaller; that’s “drink me” isn’t it:

                                 <DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                                     From="1.2" To ="1" Duration="0:0:0.1">
                                <DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                                     From="1.2" To ="1" Duration="0:0:0.1">

Add those after the existing two `DoubleAnimation` elements and run again. At first glance, it would appear that they will execute in sequence; but of course if they did, you would have seen the X co-ordinate expand before the Y. What, in fact, happens, is the last animation wins and it just contracts.

With no small help from a well known site that allows programmers to ask questions of other programmers, with the intention of writing a blog post and passing the knowledge off as their own, I found this little trick. There is a `BeginTime` property of DoubleAnimation:

                                 < DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                                     From ="1.2" To ="1" Duration="0:0:0.1"
                                                            BeginTime="0:0:0.2"/>
                                < DoubleAnimation
                                    Storyboard.TargetName="MyAnimatedScaleTransform"
                                    Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                                     From ="1.2" To ="1" Duration="0:0:0.1"
                                                            BeginTime="0:0:0.2"/>

Now try it – good eh? You can play with the “pop”, make it grow bigger, or smaller. There’s even a repeat property.

Conclusion

I intend this to be the first in a few posts on animation. Next, I intend to write about how you would do the same thing using code; and later, I’ll look at how this all works in WinRT (I’ll give you a clue – it’s not the same!).

One thought on “Animation in XAML (Part 1)

  1. Pingback: Animation in XAML (Part 3) | Arrested Developing

Leave a Reply

Your email address will not be published. Required fields are marked *