LoginSignup
6
3

More than 5 years have passed since last update.

Xamarin.Macにおけるシートいろいろ(ファイルダイアログ編)

Last updated at Posted at 2014-12-26

Problem

ファイルダイアログもシートで出せます。
シートで出すことにより,どのアプリケーションのダイアログかが明確になるので,できれば使っていきたいところです。
シートを乱発するとどうなるか,そしてこれを防ぐ方法についても本稿でご紹介します。

Prerequisite

Xamarin.Mac プロジェクトを作成し,MainWindow.xibをXCodeで開いて,このような感じにしてあります。
XCode上のUIデザイン

NSOpenPanel

いわゆるオープンファイルダイアログです。
オプションを指定することでフォルダ選択ダイアログに仕立てることも可能です。

MainWindowController.cs
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 しているのでモーダルダイアログとして表示されます。
これをシートにする場合は以下のようになります。

MainWindowController.cs
[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;
        });
}

BeginSheetEndSheetは対応させなくてはなりません。また,using句でくくると破棄タイミングがよろしくないので,代わりにReleasedWhenClosedtrueにしておきます。
ShowAsSheet

NSSavePanel

保存先の選択に使います。NSOpenPanelはこれを継承しています。こちらはシートで表示する場合だけ。

MainWindowController.cs
[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;
        });
}

NSSavePanel

必要であればAccessoryViewで何でも追加可能。

MainWindowController.cs
var img = new NSImageView(new System.Drawing.RectangleF(0, 0, 64, 64))
    { Image = NSImage.ImageNamed(NSImageName.QuickLookTemplate), ImageScaling = NSImageScale.ProportionallyUpOrDown };
panel.AccessoryView = img;

accview

Conclusion

Xamarin.Macにおけるシートいろいろはこれで完結です。
本当はシート乱発時の危険な動作についてまとめたいですが,10.9以降のAPIを使う場合は起きないようなので,大丈夫だと信じて割愛します。
ここまでのシートいろいろまとめはUnified APIでもほぼ同じコードで動作します。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3