Every body knows that Windows Presentation Foundation provides better support for UI than WinForms does in .NET 3.5 (and RC .NET 4).

You can make very beautiful application UI using Visual Studio 2008 (or the new Visual Studio 2010), but this requires very good knowledge of XAML or use other WPF design based application like Microsoft Expression Blend. I for one don’t afford Blend and had to rely entirely on Visual Studio 2010. That’s my way of learning WPF design. Code and if I get no errors see what the code does.

In this post I’ll show how to make a button “disappear” from a window and come back using a Storyboard that contains a DoubleAnimationUsingKeyFrames.

Setting up the window and button

Right open up Visual Studio 2010 RC1 (Visual Studio 2008 Pro and Express editions will work just as well) and create a new project. From the New Project Window select Windows from your language of choosing and select a WpfApplication.

image

Visual Studio will create all the necessary files and open up your MainWindow.xaml in split mode (where you have the design at the top and the XAML at the bottom) with the following code:

<Window x:Class="WpfAnimationUsingKeyFrames.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

    </Grid>
</Window>

Now lets add a button to our window. Add the following markup:

<Button x:Name=”Move”
        Content="Move!"
        Margin="3" Padding="10"
        HorizontalAlignment="Center"
        VerticalAlignment="Center">
</Button>

We’re done with setting up the window. So for you should have the following result:

image

Setting up RenderTransform

Now that we have our up we should add some RenderTransform properties to our button. We need to do this otherwise we won’t have what to animate in our storyboard when we’ll set up later.

Between your <Button> tags add the following markup:

<Button.RenderTransform>
                <TranslateTransform/>
</Button.RenderTransform>

Great! (Cheering up myself for typing this much so far) Now we have what to animate when we write our storyboard.

Setting up the Storyboard

Now that we have our button and the button is ready to accept render transformations lets write the storyboard.

Right before the <Grid> tag (which is the opening tag for our grid) add the following markup:

<Window.Resources>

</Window.Resources>

We’ll define our storyboard in the windows resources. Not sure, but I think this is the only. If some WPF developer will scream in the comments that this is all wrong, sorry, but this is how it worked for me.

Moving on. Time to finally write the storyboard. I’ll write to whole markup and explain everything afterwards. It’s not complicated just bare with me on this. Between the Window.Resources tags write the following markup:

<Storyboard x:Key="Move">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                   Storyboard.TargetName="Move" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.0100" Value="10"/>
        <SplineDoubleKeyFrame KeyTime="00:00:00.5000" Value="-350"/>
        <SplineDoubleKeyFrame KeyTime="00:00:02.0000" Value="-350"/>
        <SplineDoubleKeyFrame KeyTime="00:00:02.5000" Value="10"/>
        <SplineDoubleKeyFrame KeyTime="00:00:02.0100" Value="0"/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Time for the explaining part. Hope I don’t get this wrong.
So first of all the x:Key property of a storyboard is required in everything you declare in your windows resources. If you don’t do that you’ get an error.
Every storyboard needs to contain an Animation. It’s the only child the container of a storyboard accepts. If you attempt to add a button to a storyboard you get an error.
There are several animation’s depending on what kind of property values are your trying to animate. In this case we’re animating a Double value in the TranslateTransform’s X property, which is a Double. That’s why we have DoubleAnimation. The UsingKeyFrames is there because we are obviously using KeyFrames to animate. I’m using key frames because  I’ve done some work in Adobe After Effects and I’m to animating with Key Frames.

The BeginTime property of the animation is when the animation starts. This property is a TimeSpan value. XAML is intelligent enough convert the “00:00:00” string to TimeSpan.
Storyboard.TargetName sets the storyboard target to an element name, in this case to our Button which has x:Name property set to “Move”.
Storyboard.TargetProperty sets the storyboard target property to a property of the element which has the name set in Storyboard.TargetName property. The value of this property is bit hard to add at first but when you know how to determine what type of property is any property will be easy. If you hover over property name in Visual Studio you get a tooltip that says the full length of the property.

image

Always remember to add the property into brackets (e.g. “(PropertyPath)” ). XAML will always convert to see it’s a correct property name and give an error if it’s not.
Once you told the animation what element to target and what property of that element to animate, it’s time to set up the key frames.
In the DoubleAnimationUsingKeyFrames tags add a SplineDoubleKeyFrame. You can add as many of these as you want.
The KeyTime and Value properties say that at the value of the KeyTime, the Value of the property specified in the Storyboard.TargetProperty is the same with Value. The thing is that between “00:00:00” and “00:00:00.0100” the value animates to 10. At time “00:00:00.0050” you won’t have 0. You’ll have a value between 0 and 10. Pretty nice eh? The same principle applies to al SplineDoubleKeyFrame’s.

Now that we have defined our Storyboard it’s time to tell to button when to animate.

Starting the Storyboard

Just right before the end of </Button.RenderTransform> tag add the following markup:
<Button.Triggers>
    <EventTrigger RoutedEvent="ButtonBase.Click">
        <BeginStoryboard Storyboard="{Binding Source={StaticResource Move}}"/>
    </EventTrigger>
</Button.Triggers>

Now when you click the button it will animate. Press F5 to debug and see what we have created.

The storyboard can be started in the Code-behind. If you want to add more code when you click the button you need set button’s Click event to an event handler. Remove the markup I told you to write above and modify the <Button> to show the following:
<Button x:Name="Move"
        Content="Move!"
        Margin="3" Padding="10"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Click="Move_Click">
    <Button.RenderTransform>
        <TranslateTransform/>
    </Button.RenderTransform>
</Button>

Now in the code-behind write to following code in Window Class:
private void Move_Click(object sender, RoutedEventArgs e)
{
    (Resources["Move"] as Storyboard).Begin();
}

Be sure to add the following reference in your using section:
using System.Windows.Media.Animation;

Done

That’s it! You’re done. Hope you found this post helpful as I found it fun to write. If I made some mistakes in my explanations or if I said some wrong/stupid things please do say it in the comments.

Looking forward for some feedback.

Full XAML with EventTriggers:

<Window x:Class="WpfAnimationUsingKeyFrames.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Storyboard x:Key="Move">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="Move" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.0100" Value="10"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000" Value="-350"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.0000" Value="-350"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.5000" Value="10"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.0100" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Button x:Name="Move"
                Content="Move!"
                Margin="3" Padding="10"
                HorizontalAlignment="Center"
                VerticalAlignment="Center">
            <Button.RenderTransform>
                <TranslateTransform/>
            </Button.RenderTransform>
            <Button.Triggers>
                <EventTrigger RoutedEvent="ButtonBase.Click">
                    <BeginStoryboard Storyboard="{Binding Source={StaticResource Move}}"/>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Grid>
</Window>

Full XAML with Click Event & Full Code-behind

XAML:
<Window x:Class="WpfAnimationUsingKeyFrames.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Storyboard x:Key="Move">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="Move" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.0100" Value="10"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000" Value="-350"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.0000" Value="-350"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.5000" Value="10"/>
                <SplineDoubleKeyFrame KeyTime="00:00:02.0100" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Button x:Name="Move"
                Content="Move!"
                Margin="3" Padding="10"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Click="Move_Click">
            <Button.RenderTransform>
                <TranslateTransform/>
            </Button.RenderTransform>
        </Button>
    </Grid>
</Window>

Code-behind:

using System.Windows;
using System.Windows.Media.Animation;

namespace WpfAnimationUsingKeyFrames
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Move_Click(object sender, RoutedEventArgs e)
        {
            (Resources["Move"] as Storyboard).Begin();
        }
    }
} //Removed unused using;

Advertisements