酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xamarin.iOSでMessageBox.Showメソッドを実装する

C#を使ってクライアントアプリのコードを書く時には、MessageBoxクラスをよく使います*1しかし、Xamarin.iOSには、MessageBox.ShowメソッドとDialogResult列挙体は用意されていません。

本記事では、Xamarin.iOSでUIAlertViewではなくMessageBox.Showメソッドを使ってアラートを表示してみたいと思います。Stackoverflowのソースコードをベースにして、.NET FrameworkでのMessageBoxに近づけるように少しだけ変更を加えています。

MessageBoxResult、MessageBoxButtons列挙体を定義する

MessageBoxでどのボタンを表示させるのかと、MessageBoxでどのボタンがタップされたのかの列挙体を定義します。

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

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

MessageBox.Showメソッド本体を実装する

Xamarin.iOSでアラートを表示するを参考に実装します。注意点としては、UIAlertViewのShowメソッドは非同期メソッドですので、ユーザーがアラートのボタンをタップするのを待ってくれたりはしません。なので、alert.Showメソッド実行後にこの変数IsDisplayedがfalseに変化するのを待ちます。

    /// <summary>
    /// メッセージ ボックスを表示します。メッセージ ボックスには、テキスト、ボタンを格納できます。
    /// </summary>
    public static class MessageBox
    {
        /// <summary>
        /// 指定したテキスト、キャプション、およびボタンを表示するメッセージ ボックスを表示します。
        /// </summary>
        /// <param name="text">メッセージ ボックスに表示するテキスト。</param>
        /// <param name="caption">メッセージ ボックスのタイトル バーに表示するテキスト。</param>
        /// <param name="buttons">メッセージ ボックスに表示されるボタンを指定する MessageBoxButtons 値の 1 つ。</param>
        public static MessageBoxResult Show(string text, string caption, MessageBoxButtons buttons)
        {
            MessageBoxResult result = MessageBoxResult.Cancel;
            bool IsDisplayed = false;
            int buttonClicked = -1;
            MessageBoxButtons button = buttons;
            UIAlertView alert = null;
            
            var cancelButton = "Cancel";
            var otherButtons = null;

            switch (button)
            {
                case MessageBoxButtons.OK:
                    cancelButton = string.Empty;
                    otherButtons = new [] { "OK" };
                    break;
                    
                case MessageBoxButtons.OKCancel:
                    otherButtons = new [] { "OK" };
                    break;
                    
                case MessageBoxButtons.YesNo:
                    cancelButton = string.Empty;
                    otherButtons = new [] { "Yes", "No" };
                    break;
                    
                case MessageBoxButtons.YesNoCancel:
                    otherButtons = new [] { "Yes", "No" };
                    break;
            }
            
            if (cancelButton != string.Empty)
            {
                alert = new UIAlertView(caption, text, null, cancelButton, otherButtons);
            }
            else
            {
                alert = new UIAlertView(caption, text, null, null, otherButtons);
            }

            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; // このフラグがfalseになるとループから抜ける
            
            while (IsDisplayed)
            {
                NSRunLoop.Current.RunUntil(NSDate.FromTimeIntervalSinceNow(0.2));
            }

            switch (button)
            {
                case MessageBoxButtons.OK:
                    result = MessageBoxResult.OK;
                    break;
                    
                case MessageBoxButtons.OKCancel:
                    if (buttonClicked == 1)
                        result = MessageBoxResult.OK;
                    break;
                    
                case MessageBoxButtons.YesNo:
                    if (buttonClicked == 0)
                        result = MessageBoxResult.Yes;
                    else
                        result = MessageBoxResult.No;
                    break;
                    
                case MessageBoxButtons.YesNoCancel:
                    if (buttonClicked == 1)
                        result = MessageBoxResult.Yes;
                    else if (buttonClicked == 2)
                        result = MessageBoxResult.No;
                    break;
            }
            
            return result;
        }

        /// <summary>
        /// 指定したテキストを表示するメッセージ ボックスを表示します。
        /// </summary>
        /// <param name="text">メッセージ ボックスに表示するテキスト。</param>
        public static MessageBoxResult Show(string text)
        {
            return Show(text, string.Empty, MessageBoxButtons.OK);
        }

        /// <summary>
        /// 指定したテキストとキャプションを表示するメッセージ ボックスを表示します。
        /// </summary>
        /// <param name="text">メッセージ ボックスに表示するテキスト。</param>
        /// <param name="caption">メッセージ ボックスのタイトル バーに表示するテキスト。</param>
        public static MessageBoxResult Show(string text, string caption)
        {
            return Show(text, caption, MessageBoxButtons.OK);
        }
    }

以上でMessageBoxクラスの実装は完了です。

MessageBox.Showメソッドの使い方

さて、実装したMessageBoxクラスを使ってみましょう。

ユーザーにYes、No、Cancelの3つのボタンのうちのどれかを選択させる場合

以下にコードを示します。

void ShowMessageBox1(object sender, EventArgs e)
{
    var title = "title";
    var msg = "message";
    var buttons = MessageBoxButtons.YesNoCancel;
    
    var result = MessageBox.Show(title, msg, buttons);
    switch (result)
    {
        case MessageBoxResult.Yes:
            break;
        case MessageBoxResult.No:
            break;
        case MessageBoxResult.Cancel:
            break;
    } 
}

上記のコードを実行すると下図のようになります。

f:id:ch3cooh393:20130424130654p:plain

ユーザーにYes、Noの2つのボタンのうちのどれかを選択させる場合

以下にコードを示します。

void ShowMessageBox2(object sender, EventArgs e)
{
    var title = "title";
    var msg = "message";
    var buttons = MessageBoxButtons.YesNo;
            
    var result = MessageBox.Show(title, msg, buttons);
    switch (result)
    {
        case MessageBoxResult.Yes:
            break;
        case MessageBoxResult.No:
            break;
    } 
}

上記のコードを実行すると下図のようになります。

f:id:ch3cooh393:20130424130705p:plain

ソースコード

Gistにアップロードしていますのでご参照ください。

関連記事

Xamarin.iOSを使ってアプリ開発する際に逆引きとしてお使いください。

*1:WinRTでMessageDialogクラスが登場したからそっちに合わせても良いのかもしれませんが……