Sometimes you have some code that needs to run after a storyboard has completed. In my case I'm working on a little board game, and after each move (which I animate using a Storyboard), I need to figure out the next move, and either start a new play-animation or pass the turn to the other player.
Therefore I run in a loop until the turn is over. You can detect when a storyboard has finished when the "Completed" event triggers, but that makes for some recursive spaghetti code. It's much easier if I could just "await" the storyboard using a task. So I created the little extension method below that makes this possible. All you have to do to start and wait for the storyboard to finish is:
await myStoryboard.BeginAsync();
Below is the little extension method (which also serves as a general example on how you turn an event-based class into an awaitable Task using the TaskCompletionSource):
using System;
using System.Threading.Tasks;
using Windows.UI.Xaml.Media.Animation;
namespace SharpGIS
{
public static class StoryboardExtensions
{
public static Task BeginAsync(this Storyboard storyboard)
{
System.Threading.Tasks.TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
if (storyboard == null)
tcs.SetException(new ArgumentNullException());
else
{
EventHandler<object> onComplete = null;
onComplete = (s, e) => {
storyboard.Completed -= onComplete;
tcs.SetResult(true);
};
storyboard.Completed += onComplete;
storyboard.Begin();
}
return tcs.Task;
}
}
}
Note: This code is written for WinRT. If you want to use this for Silverlight or WPF, just change ‘Eventhandler<object>’ to ‘EventHandler’.