##Problem
ファイルダイアログもシートで出せます。
シートで出すことにより,どのアプリケーションのダイアログかが明確になるので,できれば使っていきたいところです。
シートを乱発するとどうなるか,そしてこれを防ぐ方法についても本稿でご紹介します。
##Prerequisite
Xamarin.Mac プロジェクトを作成し,MainWindow.xibをXCodeで開いて,このような感じにしてあります。
##NSOpenPanel
いわゆるオープンファイルダイアログです。
オプションを指定することでフォルダ選択ダイアログに仕立てることも可能です。
public override void WindowDidLoad()
{
base.WindowDidLoad();
OpenButton.Activated += (sender, _) => ShowOpenPanel((NSObject)sender);
}
[Export("openDocument:")]
void ShowOpenPanel(NSObject sender)
{
using(var panel = new NSOpenPanel()){
// 複数選択の可否
panel.AllowsMultipleSelection = false;
// ファイル選択の可否
panel.CanChooseFiles = true;
// ディレクトリ選択の可否
panel.CanChooseDirectories = true;
// 受け入れるファイルタイプ
// 拡張子のみ,ピリオドなし,複数指定可能
panel.AllowedFileTypes = new[]{ "txt" };
// 開くボタンのテキスト,指定しない場合はOS標準
panel.Prompt = "開く";
// モーダルウィンドウのタイトル
panel.Title = "ウィンドウタイトル";
// モーダル表示
var ret = panel.RunModal();
// キャンセルが押された場合 0 が返る
if (ret > 0)
PathField.StringValue = panel.Url.Path;
}
}
先頭の[Export]
によりセレクタを宣言することで,メニューバーの「開く」に関連付けています。
RunModal
しているのでモーダルダイアログとして表示されます。
これをシートにする場合は以下のようになります。
[Export("openDocument:")]
void ShowOpenPanel(NSObject sender)
{
var panel = new NSOpenPanel{ CanChooseFiles = true, AllowedFileTypes = new[]{ "cs" }, ReleasedWhenClosed = true };
panel.BeginSheet(Window, ret =>
{
panel.EndSheet(Window);
if (ret > 0)
PathField.StringValue = panel.Url.Path;
});
}
BeginSheet
とEndSheet
は対応させなくてはなりません。また,using
句でくくると破棄タイミングがよろしくないので,代わりにReleasedWhenClosed
をtrue
にしておきます。
##NSSavePanel
保存先の選択に使います。NSOpenPanelはこれを継承しています。こちらはシートで表示する場合だけ。
[Export("saveDocumentAs:")]
void ShowSavePanel(NSObject sender)
{
var panel = new NSSavePanel();
// 許容する拡張子
panel.AllowedFileTypes = new[]{ "cs" };
// フォルダの作成ボタンを表示
panel.CanCreateDirectories = true;
panel.ReleasedWhenClosed = true;
panel.Message = "SavePanelを通して伝えたいこと";
panel.BeginSheet(Window, ret =>
{
panel.EndSheet(Window);
if (ret > 0)
PathField.StringValue = panel.Url.Path;
});
}
必要であればAccessoryView
で何でも追加可能。
var img = new NSImageView(new System.Drawing.RectangleF(0, 0, 64, 64))
{ Image = NSImage.ImageNamed(NSImageName.QuickLookTemplate), ImageScaling = NSImageScale.ProportionallyUpOrDown };
panel.AccessoryView = img;
##Conclusion
Xamarin.Macにおけるシートいろいろはこれで完結です。
本当はシート乱発時の危険な動作についてまとめたいですが,10.9以降のAPIを使う場合は起きないようなので,大丈夫だと信じて割愛します。
ここまでのシートいろいろまとめはUnified APIでもほぼ同じコードで動作します。