この記事は [初心者さん・学生さん大歓迎!] Xamarin その1 Advent Calendar 2017 の16日目の記事です。
題について
勢いでサクッとつけてしまった題ですが、思ってたのとちょっと違うところです。
実際には、「 他プラットフォームとの互換性を最大限に維持しつつ Xamarin.Forms for MacがStoryboardと仲良くする方法」ですね。
もっと標準コンロールで
Storyboardでは
こういうコントロールを出すのは楽なのに。
(もちろん、こいつだとsegue一発なんでXamarin.Formsでもコード書きゃ終いですが)
でもDataBindingやら他機種へのポーティングを考えるとXamarin.Formsのコード使えたら楽なのに。
というわけで、いいとこ取りする簡単な方法です。
実現方法
理屈:Xamarin.Forms
Xamarin.Forms for Macの動きとして。
- Forms.Init()は適当な時に呼び出しても良い
- Forms.Init()はFormsApplicationDelegate.LoadApplicationの前に呼びださなければいけない
- ApplicationのMainPageは設定されていなくても良い
- ApplicationのMainPageが設定されていなければ、FormsApplicationDelegate.Windowは設定されていなくても良い
- FormsApplicationDelegate.LoadApplicationは最初のPage操作の前に呼び出されていなければいけない
- Xamarin.FormsのPageからNSViewControllerを作れる
理屈:Storyboard
また、Storyboard起動からの呼び出し順は、
- FormsApplicationDelegate.<<constructor>>
- NSViewController.ViewDidLoad
- FormsApplicationDelegate.DidFinishLaunching
です。
理屈:統合
なので、本来ならFormsApplicationDelegate.DidFinishLaunchingでXamarin.Formsの処理を行いますが、その流れを変えて。
- アプリ起動、UI始動までStoryboardで行う
- Forms.Init()とLoadApplicationはFormsApplicationDelegate.<<constructor>>で行う
- Application.MainPageを設定しない
- FormsApplicationDelegate.Windowも設定しない
- 表示関連はPageで用意しておき、ViewControllerにくっつける
- くっつけるのはNSViewController.ViewDidLoadで行う
- データの保持、更新処理はXamarinのBindingObjectに納める
- BindingObjectからのデータ更新はPage側で受け、表示する
という処理にします。
作ってみた
[AppDelegate] (https://github.com/yakumo/XamarinHelloWorldTest/blob/master/src/mac/HelloWorldTest/AppDelegate.cs) : Storyboard
何もしないXamarin.Forms.Applicationのサブクラス(App)を作り、それをLoadApplicationで設定しています。
これで、StoryboardのDelegateとして読み込まれ、Xamarin.Forms的には初期化を行い、WindowはStoryboardのものを使うように設定しています。
他プラットフォームでは、LoadApplicationで設定しているのはHelloWorldAppです。
MainData : Xamarin.Forms
埋め込みリソースとして登録してあるJSONを読み込み、本棚データとして保持します2。
TitlesViewController : Storyboard
StoryboardでメインウインドウのViewControllerとして設定されます。
ViewDidLoadでTitleListPageを子ViewControllerとして設定しています。
TitleListPage : Xamarin.Forms
MainDataをBindingContextとしてわりつけ、表示している本棚の中の本の一覧を表示します。
他プラットフォームだと、MasterDetailPageのDetailにわりつけてメインのページになっています。
BookshelvesViewController : Storyboard
ウインドウにわりつけられたToolBarのボタンからPopupする本棚の一覧を表示するViewControllerです。
ボタン押下でPopupまではStoryboardで設定されています。
ViewDidLoadでBookshelfListPageを子ViewControllerとして設定しています。
BookshelfListPage : Xamarin.Forms
MainDataをBindingContextとしてわりつけ、本棚一覧を表示します。
ポップアップの中身です。
他プラットフォームだと、MasterDetailPageのMasterにわりつけてます。
結論
意外に簡単にStoryboardと統合できました。
このやり方は、 Page.CreateViewController
におんぶにだっこしてもらって実現できています3。
MVVMで分けるのは微妙ではありますが、入力する量も少なくていいところではないかと思います。
-
アイコンはICOOON MONOさんのものを使用しています。 ↩
-
作った後に気づきましたが、コンストラクタはprivateの方が良いですねぃ。 ↩
-
iOSでの同じやり方は意外に難しそうです。ListViewェ…。 ↩