SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

Xamarin.Android モーダルダイアログへの誘惑

【 Xamarin 記事一覧 】

1 モーダルダイアログ

Windowsでデスクトップアプリを書いていると、当たり前のように「モーダルダイアログ」で処理を分岐して書いています。
本日は、Androidでモーダルダログを書こうと足掻いた記録です。

(1) Backボタンによるキャンセル

ダイアログボックスは、デフォルトで「BACK」キーを押すとキャンセル(クローズ)されます。
この動作を封じたい場合は、SetCancelable(false)と指定します。
SetCancelable()メソッドは、AlertDialogの基底クラスであるDialogの公開メソッドであり、DatePickerDialogなど、各種のダイアログの基底クラスでもありますので、すべてのダイアログで利用可能です。

(2) クローズ時のイベント

ダイアログは、クローズ時にDismisというイベントが発生しています。
そして、いくつかのダイアログでは、これをDismissEventというイベントや、SetOnDismissListener()メソッドで公開しています。したがって、このイベントをトラップすれば、ダイアログが閉じる際の処理は簡単です。
しかし、AlertDialogでは、何故かこれが隠ぺいされています。
AlertDialogを継承して、Dismisイベントを公開するMyAlertDialogを参考までに記録しておきます。

private void Func(){
    var dlg = new MyAlertDialogDlg(this);
    dlg.SetTitle("タイトル");
    dlg.SetMessage("メッセージ");
    //ダイアログがクローズされた際のイベント処理
    dlg.DismisEvent += (s, e) =>Toast.MakeText(this,"Dismis",ToastLength.Short).Show();
    dlg.Show();
}

//自前のAlertDialog
public class MyAlertDialogDlg : AlertDialog{
    public MyAlertDialogDlg(Context context): base(context){}
    //イベント定義
    public event DismisEventDelegate DismisEvent;
    public delegate void DismisEventDelegate(object sender, EventArgs e);
    //Dismisイベントをオーバーライドしてイベントとして公開する
    public override void Dismiss(){
        base.Dismiss();
        if (DismisEvent != null){
            DismisEvent(this, null);
        }
    }
}

2 部品は揃った

ダイアログの生死イベントがハッキリしたので、「部品は揃った!」という事で、スレッド待機させようと色々悩んだのですが・・・Androidで、スレッドを待機させるという処理は、あまりお勧めでは無いようで、モーダルなダイアログを書こうとした途端に、コードがグタグタになってしまいます。
※特にUIスレッドの待機は不可能

(1) 結局やりたい事はコレだ

結局、下記のような書き方ができれば、一応OKという事で、スレッドを待機させない方向での解決に方向転換!
よーするに、こういう風に書きたいだけだ・・・


 if (DialogResult.OK == MessageBox.Show("よろしいですか", "タイトル", MessageBoxButtons.OKCancel)) {
   //OKの時の処理
}

(2) ラムダ式でそれ風に

これでどうだろうか・・・
下記のMessaegBoxクラスは、OKやCancelを押した時の処理を、delegateで受け取ります。

delegate void funcDelegate();
class MessageBox{
    public static void Show(Context context, string msg, string title, funcDelegate Ok = null, funcDelegate Cancel = null){
        var dlg = new AlertDialog.Builder(context);
        dlg.SetTitle(title);
        dlg.SetMessage(msg);
        dlg.SetPositiveButton( //OKボタンの処理
           "OK", (s, a) => {
               if (Ok != null){ //func OKが指定されている場合、それを実行する
                   Ok();
               }});
        dlg.SetNegativeButton( //Cancelボタンの処理
           "Cancel", (s, a) => {
               if (Cancel != null){ //func Cancelが指定されている場合、それを実行する
                   Cancel();
               }});
        dlg.Create().Show();
    }
}

使い方は、下記のとおりです。


MessageBox.Show(this, "よろしいですか", "タイトル", Ok:() => {
    //OKの時の処理
    Toast.MakeText(this, "OK", ToastLength.Short).Show();
});


MessageBox.Show(this, "よろしいですか", "タイトル", Cancel:() => {
    //Cancelの時の処理
    Toast.MakeText(this, "Cancel", ToastLength.Short).Show();
});

今日のあまりにも成果のない結論・・・「モーダルダイアログはやめとこう」

【 Xamarin 記事一覧 】