Async Support for Executing Storyboards in UWP and WinUI

Sometimes I forget just how old and dated XAML is, and how little advances Microsoft has made to make it easy to work with. With the move to WinUI, hopefully we’ll start to see some much needed improvements – we’ve seen some already with the ability to define row and column definitions as a single attribute eg RowDefinitions=”2*,*,*,*”. In this post I’m going to provide a simple solution to an issue I ran into recently where I wanted to run a Storyboard (defined in XAML) and then perform some action once the Storyboard had completed.

To set the scene, a Storyboard is a relatively simple class that’s used to control an animation sequence, most commonly defined in XAML. It has methods to Begin, Pause, Resume, Stop etc and has a Completed event for when the animation sequence has finished. What it doesn’t have is any async support, meaning that you can’t await the animation sequence before performing the next action.

Luckily the solution for this is to use a TaskCompletionSource to wrap the Begin and Completed event into a Task that can be awaited.

public static class StoryboardHelper
{
    public static Task RunAsync(this Storyboard storyboard)
    {
        var tcs = new TaskCompletionSource<object>();
        EventHandler<object> completion = null;
        completion = (sender, args) =>
        {
            storyboard.Completed -= completion;
            tcs.SetResult(null);
        };
        storyboard.Completed += completion;
        storyboard.Begin();
        return tcs.Task;
    }
}

Note: We could have used the non-generic TaskCompletionSource here but this isn’t supported across all Uno targets.

Now, all we need to do is await RunAsync on our storyboard before moving onto the next action.

// Do stuff before running the storyboard
await myStoryboard.RunAsync();
// Do the next thing after storyboard completes

1 thought on “Async Support for Executing Storyboards in UWP and WinUI”

Leave a comment