Search code examples
c#wpfxamlanimationhamburger-menu

How to make Hamburger Menu Transition Animation in XAML only


I want to create the Hamburger Menu Transition Animation in XAML only. I only found tutorials and examples of how to do this with code-behind. But this is something I want to avoid at all costs.

This is how the animation looks like: Animation (no direct GIF possible at the moment)

One example I found

XAML:

<Window.Resources>
    <Storyboard x:Key="OpenMenu">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="43.5"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle1">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-43.5"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle2">
            <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="GridMenu">
            <EasingDoubleKeyFrame KeyTime="0" Value="70"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="200"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="CloseMenu">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle">
            <EasingDoubleKeyFrame KeyTime="0" Value="43.5"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle1">
            <EasingDoubleKeyFrame KeyTime="0" Value="-43.5"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle2">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="GridMenu">
            <EasingDoubleKeyFrame KeyTime="0" Value="200"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="70"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>

code-behind:

    private void ButtonMenu_Click(object sender, RoutedEventArgs e)
    {
        if(StateClosed)
        {
            Storyboard sb = this.FindResource("OpenMenu") as Storyboard;
            sb.Begin();
        }
        else
        {
            Storyboard sb = this.FindResource("CloseMenu") as Storyboard;
            sb.Begin();
        }

        StateClosed = !StateClosed;
    }

Is there anyway to achive the same result using XAML-only. I dont want any code-behind for this animation...

I know how to create each Storyboard for the animation itself. But the same button has to execute two different Storyboards, depending on the state of the menu?


Solution

  • Here is an example using a ToggleButton instead. Since the ToggleButton has built in Checked / Unchecked events, you can use those in EventTriggers to run your storyboards.

    <ToggleButton ... >
        <!-- Your menu icon XAML/rectangles go here -->
        <ToggleButton.Triggers>
            <EventTrigger RoutedEvent="ToggleButton.Checked">
                <EventTrigger.Actions>
                    <BeginStoryboard Storyboard="{StaticResource OpenMenu}" />
                </EventTrigger.Actions>
            </EventTrigger>
            <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                <EventTrigger.Actions>
                    <BeginStoryboard Storyboard="{StaticResource CloseMenu}" />
                </EventTrigger.Actions>
            </EventTrigger>
        </ToggleButton.Triggers>
    </ToggleButton>