Currently, Windows Phone Choosers work is by invoking the Show method and then subscribing the Completed event and waiting for it to be invoked.
Wouldn’t it be great to just use await chooser.ShowAsync()
and get the results immediately?
All choosers extend the ChooserBase<TTaskEventArgs> class, and it’s exactly for this class that we are going to use to create a ShowAsync extension method.
We start by creating the extension method signature:
public static class ExtensionMethods{ public static Task<TTaskEventArgs> ShowAsync<TTaskEventArgs>(this ChooserBase<TTaskEventArgs> chooser) where TTaskEventArgs : TaskEventArgs { }}
The async
methods are required to return void, Task, or Task<TResult> in order to be invoked with the await
keyword. So our method will return a Task<TTaskEventArgs>
value, where the TTaskEventArgs
generic type must be a TaskEventArgs subtype.
We will need to use a TaskCompletionSource object so we can return a Task and later on set the result of the asynchronous operation.
var taskCompletionSource = new TaskCompletionSource<TTaskEventArgs>();
Next we will add the code for the normal Chooser handling:
EventHandler<TTaskEventArgs> completed = null;completed = (s, e) => { chooser.Completed -= completed; taskCompletionSource.SetResult(e);};chooser.Completed += completed;chooser.Show();
Notice that we are removing the event handler after it gets invoked as not to have a memory leak! All that is missing now is just returning the Task object:
return taskCompletionSource.Task;
And that’s it!
Here’s how the full extension method should look:
public static class ExtensionMethods { public static Task<TTaskEventArgs> ShowAsync<TTaskEventArgs>(this ChooserBase<TTaskEventArgs> chooser) where TTaskEventArgs : TaskEventArgs { var taskCompletionSource = new TaskCompletionSource<TTaskEventArgs>(); EventHandler<TTaskEventArgs> completed = null; completed = (s, e) => { chooser.Completed -= completed; taskCompletionSource.SetResult(e); }; chooser.Completed += completed; chooser.Show(); return taskCompletionSource.Task; }}
You can download a sample code for this directly from the Microsoft Code Gallery.