Xamarin.Macでモーダルウインドウを作成する
MonoMacおよびXamarin.Macでモーダルウインドウを表示する。
目次
概要
Mac OS Xでは一般的にWindows風のモーダルウインドウではなくシート(親ウインドウに固定されたモーダルウィンドウ)を使うらしい。シートは親ウインドウがどれか明確なのでウインドウ開きすぎな環境ではよいよいだ。
しかしながらが、特定業務専用機と化しているMacでは親ウインドウを見ながら項目入力したいのとの苦情が殺到した。そのためWindows風のモーダルウインドウを実現する方法を模索している。
実装1
戻り値の準備
モーダルウインドウの戻り値用にWinFormsのDialogResult風に列挙体を用意しておくと可読性が向上する気がする。
// モーダルウインドウの戻り値用
public enum ModalResult
{
Unknown = 0,
OK = 1,
Cancel = 2,
}
親ウインドウから子ウインドウを呼び出す
MonoMacでモーダルウインドウを表示するには NSApplication.SharedApplication.RunModalForWindowメソッドを使うようだ。 親ウインドウは勝手に認識されている?
public partial class MainWindowController : MonoMac.AppKit.NSWindowController
{
// 中略
public override void WindowDidLoad()
{
base.WindowDidLoad();
showSubWindowButton.Activated += (object sender, EventArgs e) => {
var sub = new SubWindowController();
var ret = NSApplication.SharedApplication.RunModalForWindow(sub.Window);
if (ret == (int)ModalResult.OK)
{
Console.WriteLine("ok");
}
};
}
}
子ウインドウを閉じる
子ウインドウを閉じるにはNSApplication.SharedApplication.StopModalWithCodeメソッドを使うようだ。このメソッドを呼ばずに子ウインドウを閉じると親ウインドウに制御が戻らないので注意すること。
この例では子ウインドウが普通に×ボタンで閉じる際に「ModalResult.OK」を返している。ダイアログ風にするのであればOKボタンやキャンセルボタンを用意して、それらが押した際にNSApplication.SharedApplication.StopModalWithCodeメソッド呼ぶとよいようだ。
public partial class SubWindowController : MonoMac.AppKit.NSWindowController
{
// 中略
public override void AwakeFromNib()
{
base.AwakeFromNib();
this.Window.WillClose += (object sender, EventArgs e) => {
Console.WriteLine("willClose");
NSApplication.SharedApplication.StopModalWithCode((int)ModalResult.OK);
};
}
}
なお、NSApplication.SharedApplication.StopModalWithCodeはウインドウのモーダル化が解除されるだけでウインドウ自体は閉じない。ボタンなどを押されたときにモーダルウインドウを閉じる場合にはthis.Window.Closeを呼んでやると良いようだ。
ModalResult _result = ModalResult.Cancel;
public override void AwakeFromNib()
{
base.AwakeFromNib();
// ----------------------------------------------------
this.Window.WillClose += (object sender, EventArgs e) => {
Console.WriteLine("WillClose");
NSApplication.SharedApplication.StopModalWithCode((int)_result);
};
// cancelButtonはInterfaceBuilderで貼付けたNSButton
cancelButton.Activated += (object sender, EventArgs e) => {
Console.WriteLine("cancelButton");
_result = ModalResult.Cancel;
this.Window.Close();
};
// cancelButtonはInterfaceBuilderで貼付けたNSButton
okButton.Activated += (object sender, EventArgs e) => {
Console.WriteLine("okButton");
_result = ModalResult.OK;
this.Window.Close();
};
}