Xamarin(その2) Advent Calendar 2016 – Qiita の10日目の記事です。Xamarin に関する記事ということで、流行りの Xamarin.Forms を使ってみましょう…じゃなくて、ビルドしてみましょうという記事です。素直に nuget から NuGet Gallery | Xamarin.Forms 2.3.3.175 をダウンロードするならば、それでいいんですよ。でも、Forms のバグがなんだとか、機能が不足だからとか、ネイティブの機能を使うためにはなんたらのサービスを使ってとかいう前に、「OSS なんだから自分で追加すればええやん」という思想…で、できたらいいなーと思った訳です。ええ「感想」です。
以前、Xamarin.Forms 用のプレビューアをアルファ版で公開 | Moonmile Solutions Blog を作ったときに(これは途中で止めてしまいました。いちいち Xamarin.Forms のバージョンアップに付き合うのも大変過ぎる)思ってたのですが、内部で XAML をパースしている部分を弄ればこの手のビューは結構簡単にできます。当時の難点は、XAML をロードしたときに、内部的に x:Class で参照してる部分を探そうとしたり、無効なタグや属性を指定するとエラーを発生してしまうということでした。実は、WPF や UWP の XAML のパーサーも同じ仕組みで「内部的に何らかの制限」があることは薄々分かってはいるのですが、なんせパーサー自体がライブラリ内にあってコードが公開されていないのでなんとも…という状態だったのです。で、晴れて Xamarin.Forms が OSS になった ので、このあたりの調節もできそうという訳です(WPFやUWPのほうの XAML パーサーは公開されていないのですが、まあ、ひとつあれば十分です)。
そんな訳で、具体的にどのように活用するのかは脇に置いて、Xamarin.Forms のビルドを確認してみましょう。Xamarin.Formsのソースコードをビルドしてテストを実行してみた – Qiita の「buildします」のところを詳しくいきます。
コードをダウンロードする
github の https://github.com/xamarin/Xamarin.Forms からコードをダウンロードします。
git clone https://github.com/xamarin/Xamarin.Forms.git しても良いし zip でダウンロードした後に解凍してもよいでしょう。ブランチを変えて、master 以外のコードをダウンロードしても ok です。
手を加えてしまったコードは本家へプルリクしない限り(そして取り入れられない限り)あなただけのコードになります。なので、思う存分、改変してしまいましょう。まあ、改変してしまって動かなくなっても自己責任なのですが、実験的にあれこれと好きなようにやってみるのもよいかなと。
ビルドする
qwerty2501 さんも書いていますが、実はビルド時にエラーがでます。どうやら Maps あたりのビルドにあれこれと設定がいる模様なのですが、私が欲しいのは Xamarin.Forms.Xaml なので、これがうまくビルドできる位置だけを探っていきます。
いくつかのコードみていくと、サンプルコードらしきものが見えます。
- /Control Gallery/Xamarin.Forms.ControlGallery.Android
- /Pages Gallery/PageGallery.Droid
の2つです。「Control Gallery」のほうが、たくさんのサンプルが含まれていそうですが、残念ながら maps を含んでいるのでうまくビルドができません。もうひとつの「Pages Gallery」のほうは、Xamarin.Forms.Pages を作った簡単なものなので、ビルドが通ります。ここでは Android のほうだけビルドしていますが、iOS のほうもビルドできるでしょう。
Hyper-V のエミュレータで動かすと、こんな感じの画面がでてきます。
参照設定をみてみる
Xamarin.Forms が NuGet からダウンロードされていないことを確認するために、共有プロジェクトの PageGallery の参照設定を見てみましょう。
プロジェクト → ソリューション を見ると各種のプロジェクト自身が参照されていることがわかります。
きちんと自前の Xamarin.Forms.* の NuGet 設定をしてもよいのですが、ここで出来上がった PageGallery/bin/Debug/ 内の各種 DLL をコピーして使ってもよいでしょう。あるいは、どうせ自前なのですが、Xamarin.Forms のプロジェクト自体をコピーして使っても構いません。
ちなみに XAML パーサーは何処にあるのか?
XAML パーサーは、https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Xaml/XamlParser.cs の Xamarin.Forms.Xaml.XamlParser.ParseXaml() でパースできるようになっています。XmlReader を使って読み込むようにしてあるので、XDocument 渡しにするのは難しくないでしょう。これと XamlLoader を改変してやれば、動的に XAML を読み込みかつ内部での x:Class やバインド先の ViewModel を切り替えることもできると思います。
あと、ちょっと興味深いのが Xamarin.Forms.Xaml.Xamlg プロジェクトですね。所謂、*.xaml からコードビハイドの *.g.cs を出力するツールです。ビルド時に xamlg ツールを使ってコードビハイド用の *.g.cs ファイルを出力しているところです。C# の場合は、*.g.cs として用意されているのですが、F# の場合はこれが対応していないために *.g.fs のようなコードを出力できません。このため Xamarin.Forms で XAML を使うときは、コードで XAML を組み立てる必要があるのですが、ここを自前実装すると F# でも C# と同じように XAML ファイルを使えるようになります。まあ、ビルドプロセス(MSBuildに戻ったし)を変えないといけないので、結構大変かもしれませんが。
と、そんな訳で、具体的なコードは間に合わなかった(本当は、タップのコードを入れ込みたかったのだが時間がなかった)ので、ここでおしまいですが、まあ、オレオレ Xamarin.Forms ができそうな感じにはなったと思います。実際、オレオレな Xamarin.Forms を作るかどうかは別としても、こんな風にライブラリが動いているんだという参考にでも。