The problem
I came across this problem while writing an Android app for myself using Xamarin. Here's a shortened version of my problem.
-
DisplayAlertis the simplest way to prompt the user with a question (ex: "Would you like to continue?"). DisplayAlertis an async call.- Unfortunately Button
Clickedevent handlers (which is often where these calls are made) must have a non-async function signature; meaningawaitcannot be performed onDisplayAlert
This means you cannot write code like the following:
myButton.Clicked += Button_Clicked; <<< ERROR! Wrong return type
...
private async Task Button_Clicked(object sender, EventArgs e)
{
var result = await DisplayAlert("", "Continue?", "Ok", "Cancel");
if (result)
{
// Do something
}
}
The Fix: ContinueWith
The solution was to use a call to ContinueWith on the Task returned by DisplayAlert. ContinueWith takes an Action
myButton.Clicked += Button_Clicked;
...
private void Button_Clicked(object sender, EventArgs e)
{
DisplayAlert("", "Continue?", "Ok", "Cancel").ContinueWith(task =>
{
if (task.Result == true)
{
// Do something
}
});
}
UI Updates on the Main UI Thread!
We're not quite done yet. Often times the code within the ContinueWith does something that updates the UI. If you've done any multi-threaded coding on a UI you'll recall that all UI changes must be done on the main thread.
Thankfully Xamarin has a simple fix for that: BeginInvokeOnMainThread. The solution now looks like:
myButton.Clicked += Button_Clicked;
...
private void Button_Clicked(object sender, EventArgs e)
{
DisplayAlert("", "Continue?", "Ok", "Cancel").ContinueWith(task =>
{
if (task.Result == true)
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
// Do some UI updates
});
}
});
}