Messagebox.Show and DialogResult equivalent in MonoTouch

I think this approach using async/await is much better, and doesn't suffer from freezing the app when rotating the device, or when the autoscrolling interferes and leaves you stuck in the RunUntil loop forever without the ability to click a button (at least these problems are easy to reproduce on iOS7).

Modal UIAlertView

Task<int> ShowModalAletViewAsync (string title, string message, params string[] buttons)
{
    var alertView = new UIAlertView (title, message,  null, null, buttons);
    alertView.Show ();
    var tsc = new TaskCompletionSource<int> ();

    alertView.Clicked += (sender, buttonArgs) => {
        Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);      
        tsc.TrySetResult(buttonArgs.ButtonIndex);
    };    
    return tsc.Task;
}       

Based on the Miguel's coded, here is a convenient replacement of standard MessageBox:

using System;
using System.Drawing;
using MonoTouch.UIKit;
using MonoTouch.Foundation;
using System.Collections.Generic;

namespace YourNameSpace
{

    public enum MessageBoxResult
    {
        None = 0,
        OK,
        Cancel,
        Yes,
        No
    }

    public enum MessageBoxButton
    {
        OK = 0,
        OKCancel,
        YesNo,
        YesNoCancel
    }

    public static class MessageBox
    {
        public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton buttonType)
        {
            MessageBoxResult res = MessageBoxResult.Cancel;
            bool IsDisplayed = false;
            int buttonClicked = -1;
            MessageBoxButton button = buttonType;
            UIAlertView alert = null;

            string cancelButton = "Cancel";
            string[] otherButtons = null;

            switch (button)
            {
                case MessageBoxButton.OK:
                    cancelButton = "";
                    otherButtons = new string[1];
                    otherButtons[0] = "OK";
                    break;

                case MessageBoxButton.OKCancel:
                    otherButtons = new string[1];
                    otherButtons[0] = "OK";
                    break;

                case MessageBoxButton.YesNo:
                    cancelButton = "";
                    otherButtons = new string[2];
                    otherButtons[0] = "Yes";
                    otherButtons[1] = "No";
                    break;

                case MessageBoxButton.YesNoCancel:
                    otherButtons = new string[2];
                    otherButtons[0] = "Yes";
                    otherButtons[1] = "No";
                    break;
            }

            if (cancelButton.Length > 0)
                alert = new UIAlertView(caption, messageBoxText, null, cancelButton, otherButtons);
            else
                alert = new UIAlertView(caption, messageBoxText, null, null, otherButtons);

            alert.BackgroundColor = UIColor.FromWhiteAlpha(0f, 0.8f);
            alert.Canceled += (sender, e) => {
                buttonClicked = 0;
                IsDisplayed = false;
            };

            alert.Clicked += (sender, e) => {
                buttonClicked = e.ButtonIndex;
                IsDisplayed = false;
            };

            alert.Dismissed += (sender, e) => {
                if (IsDisplayed)
                {
                    buttonClicked = e.ButtonIndex;
                    IsDisplayed = false;
                }
            };

            alert.Show();

            IsDisplayed = true;

            while (IsDisplayed)
            {
                NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.2));
            }

            switch (button)
            {
                case MessageBoxButton.OK:
                    res = MessageBoxResult.OK;
                    break;

                case MessageBoxButton.OKCancel:
                    if (buttonClicked == 1)
                        res = MessageBoxResult.OK;
                    break;

                case MessageBoxButton.YesNo:
                    if (buttonClicked == 0)
                        res = MessageBoxResult.Yes;
                    else
                        res = MessageBoxResult.No;
                    break;

                case MessageBoxButton.YesNoCancel:
                    if (buttonClicked == 1)
                        res = MessageBoxResult.Yes;
                    else if (buttonClicked == 2)
                        res = MessageBoxResult.No;
                    break;
            }

            return res;
        }

        public static MessageBoxResult Show(string messageBoxText)
        {
            return Show(messageBoxText, "", MessageBoxButton.OK);
        }

        public static MessageBoxResult Show(string messageBoxText, string caption)
        {
            return Show(messageBoxText, caption, MessageBoxButton.OK);
        }
    }
}

To do this, what you can do is to run the mainloop manually. I have not managed to stop the mainloop directly, so I instead run the mainloop for 0.5 seconds and wait until the user responds.

The following function shows how you could implement a modal query with the above approach:

int WaitForClick ()
{
    int clicked = -1;
    var x = new UIAlertView ("Title", "Message",  null, "Cancel", "OK", "Perhaps");
    x.Show ();
    bool done = false;
    x.Clicked += (sender, buttonArgs) => {
        Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
    clicked = buttonArgs.ButtonIndex;
    };    
    while (clicked == -1){
        NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
        Console.WriteLine ("Waiting for another 0.5 seconds");
    }

    Console.WriteLine ("The user clicked {0}", clicked);
    return clicked;
}