XAML とは何か? … Microsoft だけのものじゃない

XAML を勉強しておけば将来役に立つよ…と Microsoft 様よりお達しがあって久しいのですが、そもそも、XAML ってのは何?ってのが昨日気になって調べていました。データの形式だけで見れば、XML 形式なのですが、あえて「XAML」とするところに意味はあるのか?かつ、Xamarin.Forms で使われている XAML は XAML と言えるのか?って話です。

Japan Xamarin User Group (JXUG)
https://www.facebook.com/groups/xm.jxug/
Using Workflow Markup
http://msdn.microsoft.com/en-us/library/vstudio/ms735921(v=vs.90).aspx

榎本さんの話で、Xamarin.Forms 以外にも WF(Workflow)でも使われているそうです。中身を見ると、XML でも良いような気がするけど、なぜに XAML なのか?

XAML は仕様が公開されている

結論から言えば、XAML の仕様は公開されています。Microsoft 自身が MS-XAML として公開していて、それに基づいて WPF やストアアプリの XAML を作っています。当然、WF の XAML も作っていて、同じように Xamarin.Forms の XAML もこれに基づいている(ハズ)です。

XAML 構文の詳細
http://msdn.microsoft.com/ja-jp/library/ms788723(v=vs.110).aspx

の中にある MS-XAML をクリックすると、公開しようの PDF に至ります。Silverlight などの XAML は以下でも公開されています。

Microsoft Domain-Specific Languages
http://msdn.microsoft.com/en-us/library/dd361847.aspx

ついでに言うと、Excel のファイルを保存したときにできる .xlsx の形式とか、VBA の仕様とかも公開されています。Microsoft は、この公開情報に基づいてデータを作っている(あるいは拡張している)ので、まあ、Office データの互換フォーマット率なんかは、このあたりを元にすれば適切かなーと思ったり。

XML と XAML の違い

SPEC をざっと読むと、いくつかの違いがあります。XAML ⊂ XML な訳だから、XML の形式に基づいてはいますが、いつかの拡張があるってことです。

  • namespace で http://schemas.microsoft.com/winfx/2006/xaml が必須
  • x:Class で実クラスにマッピングする
  • tagName.propName のように、ドットでつながった名前が特別扱い
  • attrName=”{Binding xxxx}” のような、属性値に {…} を指定したときに特別扱い

他にもいくつか細かい違いがあるのですが(「Name と x:Name を同時に定義してちゃいけない」という仕様がある!)、まあこんな感じです。

WPF やストアアプリ、Windows Phone で規定されているコントロールとかは XAML 本体とは別ものなので、Xamarin.Forms の XAML の共通部分も、ここの MS-XAML にあっている(はず)です。

名前空間 http://schemas.microsoft.com/winfx/2006/xaml を利用

XAML では x:Name のように、x 付きの属性が頻発するのですが、これが XAML の肝っぽいですね。名前空間のエイリアスが「x:」でつけられているのですが、「xxx:」のように変更することも可能です。

乱暴なことを言えば、このスキームを設定するだけで、XAML です、と言い張ることもできる…かもしれません。あまり意味はありませんが。

x:Class で実クラスにマッピングする

XAML は、XAML ファイル単体で存在するとは少なくて、特定のクラスとマッピングされます。XAML 内にある x:Name を x:Class で指定したクラスのフィールド(プロパティでも良い?)やイベントにバインドしています。なので、特にバインドしない場合は、x:Class を書かなくても良いと思うのですが。このバインド自体が、*.g.cs のようなバックグラウンドのコードを吐くので、ビルド環境依存になるような気がするんですけどね。このために Visual Studio で普通の C#/VB の XAML を書いたときにはバインド用の中間ファイルが作られます。F# の場合は、この中間ファイルを作らない(作れない?)ので、x:Class を指定せずにタイププロバイダを使うという方法を取っています。

ちなみ、自前の XamarinForms のプレビューアは x:Class を指定しているけど、動的にクラスをバインドするという手法を取っていて、動的なコードを作りません。なので、XAML 解析コードを自前で作れば、ちょっと違ったマッピングの仕方もできるということです。

ドットでつながった名前を特別扱いする

XAML を調べていた理由として、このドット付きの名前があります。<TextBlock Text=”…” Grid.Row=”0″ のように、親の Grid に設定をしたり、<TextBlock.Background>Black</TextBlock.Background> のようにプロパティを設定したりできます。ドット記号自体は名前に使ってよいことは調べたのですが、このドットの前後を SPEC で規定しているのか否か?ってところです。

MS-XAML を見ると、6.5.1. DottedXamlName として、ドット付き名前が規定されています。これに基づいて、ドット前後の XamlName に分けて XAML 解析を行うという訳です。

属性値に {…} を使う

XAML の拡張として、属性値に {…} が使われているのですが、これはどういうフォーマットなのか?自由フォーマットなのか?と思っていましたが、これも MS-XAML で規定されています。

6.6.7.1. Markup Extension Parsing なところで、MarkupExtension としてフォーマットが決まっています。なので、Text=”{Binding text}” のような感じなのも勝手なフォーマットを使っている、という訳ではないのです。

XAML 形式を解析する

Xaml ファイルをロードしてマッピングする場合は、XamlReader を使います。ストアアプリのような WinRT の場合は、いかな感じで読み込みます。

[WinRT] XElement を使い XAML を構築して動的に XamlReader.Load で読み込む技 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6556

WinRT の場合、Windows.UI.Xaml.Markup 名前空間にあるのですが、WPF のような本来(?)の XAML は、System.Xaml の下にあります。何故、System.Xaml から動いてしまったのか、Xamarin.Forms に System.Xaml が無いのはなぜなのか、は分かりませんが、処々の事情がありそうです。

  • XamlXmlReader
  • XamlObjectReader
  • XamlServices

XAML 解析とマッピング自体は上記の 3つのクラスを使えばよさそうです。Read メソッドで SAX 風にタグを読み込んでマッピング部分を自前で書いていけばよいのです。Xamarin.Forms プレビュアは、XML として読み込んだ後に、独自に解析をしているので、このあたりを変えたいな…とは思ってはみたものの、Xamarin.Form には、というか mono には System.Xaml がないんですよね…ともったらあるよ( http://www.mono-project.com/archived/systemxamlhacking/ )。ストアアプリ WinRT のほうにも System.Xaml がないので、互換ライブラリを作って PCL 化するのがいいんですかね。

ここまで書いて、一切 UI な部分が出てきませんが、そうなんです。XAML は UI とは全く関係ないんですね。ってことは、普通にクラスにマッピングする XML 形式のデータであればよいのです。なるほど。

連載:Windowsストア・アプリ開発入門:第5回 データを画面に表示する (1/5) – @IT
http://www.atmarkit.co.jp/ait/articles/1311/01/news095.html

のように、デザイン時のデータ形式は、JSON と XAML が選べます。そうなんです。XML じゃなくて XAML なんですよ。これは、まあ、そういう意味があるということです(逆に言えば、クラス構造を外して、JSON のように XML 形式でも十分ではないか?とも言えますが)。

カテゴリー: XAML パーマリンク