Workaround for Xamarin.Forms' DisplayAlert Bug (Alert Being Shown Twice)

While I was answering questions in StackOverflow, I encountered a question about Xamarin.Forms’ DisplayALert. My first answer was so wrong and it’s not solving any problem. I was trying to correct something which is already correct. I’ll be honest, I haven’t actually tried out his code. So, I tried the code myself. I thought it was only a bug within his app, but apparently, it’s been a bug for a very long time.

I’m talking about this code block:

var resp = await DisplayAlert("","Are you sure want to Logout?","Yes", "No");
if (resp)
{ 
   //Do something
}

Bug

This results into two popups, which is obviously not expected. This is an actual bug and is reported to Bugzilla already back in December and I guess it’s still not fixed.

Solution

So, instead, I looked for other workarounds, because I know that I’ll encounter this problem in the future, too. And also, I want to help the guy from StackOverflow. What I’ve found is that you need to need to invoke the Display Alert in the main UI thread using Xamarin.Forms.Device.BeginInvokeOnMainThread. We need to pass in an Action that will execute the DisplayAlert to the main UI thread:

  Device.BeginInvokeOnMainThread(new Action(async () =>
  {
       if(await DisplayAlert("", "Are you sure want to Logout?", "Yes", "No"))
       {
         //Do something
       }
  }));

This is used in order to do something on the UI thread. So it’s normally called from a background thread, in order to manipulate the UI, which can only be done on the UI thread. The body of the lambda expression is the code which you want to execute in the UI thread. This is the same with how Silverlight/WPF/WP8.1, iOS, and Android access the GUI thread:

Silverlight/WPF/etc.

Deployment.Current.Dispatcher.BeginInvoke( ()=> {
 if(await DisplayAlert("", "Are you sure want to Logout?", "Yes", "No"))
       {
         //Do something
       }
});

And for Android: AndroidRunOnUiThread(() => delta)

Same thing for iOS: InvokeOnMainThread

This fixes the issue, because we’re now invoking it on the Main UI thread. Our DisplayAlert will now be executed once. So, yeah, for now, we can use this workaround. But, hopefully, they fix the bug, so we can just execute it without the BeginInvokeOnMainThread method. I hope this can help you with your development, especially those guys who’s encountering this right now.

Resource:


Written on April 5, 2017