Basic animations in WPF

07 May 2024

Category: Mini

Hi everyone,
This is super basic example of how to use animations in WPF. I used a Resource Dictionary to store animations and then merged it into the main window. The animations are triggered by button clicks. The first button triggers the animation of the second button appearing and the second button triggers the animation of the first button appearing. The animations are simple scale and opacity animations.

Important takeaways:

Main Window:

 <Window x:Class="ButtonAnimationExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Button Animation Example" Width="400" Height="300">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- Merge the resource dictionary containing animations -->
                <ResourceDictionary Source="Resources/Animations.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            
            <Style TargetType="Button">
                <Setter Property="Height" Value="50"></Setter>
                <Setter Property="Width" Value="100"></Setter>
                <Setter Property="FontSize" Value="20"></Setter>
                <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                <Setter Property="VerticalAlignment" Value="Center"></Setter>
                <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            </Style>
        </ResourceDictionary>
    </Window.Resources>
    
    <Grid VerticalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <!-- Button that triggers the animation -->
        <Button x:Name="TriggerButton" Content="Click Me" 
                Grid.Row="0"
                Click="TriggerButton_Click"
                >
            <Button.RenderTransform>
                <ScaleTransform ScaleX="1" ScaleY="1"/>
            </Button.RenderTransform>
        </Button>
        <!-- Button to appear with animation -->
        <Button x:Name="TargetButton" Content="Aaaaand back" 
                Grid.Row="1"
                Opacity="0"
                Click="TargetButton_OnClick"
                Width="200"
                >
            <Button.RenderTransform>
                <ScaleTransform ScaleX="0" ScaleY="0"/>
            </Button.RenderTransform>
        </Button>
    </Grid>
</Window>

Code Behind:

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

namespace ButtonAnimationExample
{
    public partial class MainWindow : Window
    {
        private readonly Storyboard _storyboardButtonShow;
        private readonly Storyboard _storyboardButtonHide;

        public MainWindow()
        {
            InitializeComponent();
            // Access animations from the merged resource dictionary
            _storyboardButtonShow = (Storyboard) FindResource("StoryboardButtonShow");
            _storyboardButtonHide = (Storyboard) FindResource("StoryboardButtonHide");
        }

        private void TriggerButton_Click(object sender, RoutedEventArgs e)
        {
            _storyboardButtonShow.Begin(TargetButton);
            _storyboardButtonHide.Begin(TriggerButton);
        }

        private void TargetButton_OnClick(object sender, RoutedEventArgs e)
        {
            _storyboardButtonHide.Begin(TargetButton);
            _storyboardButtonShow.Begin(TriggerButton);
        }
    }
}

Resources/Animations.xaml:

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- Define the animation for scaling and opacity -->
    <Storyboard x:Key="StoryboardButtonShow">
        <!-- Scale animation X-->
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                       Duration="0:0:1.0">
            <!-- Easing functions are used to make the animation more smooth -->
            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
        <!-- Scale animation Y-->
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                       Duration="0:0:1.0">
            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
        <!-- Opacity animation -->
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
                         Duration="0:0:1.0">
            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

    <!-- Define the reverse animation -->
    <Storyboard x:Key="StoryboardButtonHide">
        <!-- Scale animation X-->
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                       Duration="0:0:0.5">
            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <!-- Scale animation Y-->
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                       Duration="0:0:0.5">
            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <!-- Opacity animation -->
        <DoubleAnimation Storyboard.TargetProperty="Opacity"
                         Duration="0:0:0.5" To="0"/>
    </Storyboard>

</ResourceDictionary>

Cheers!

Petr