XAML とは何か?


今更ですが、XAMLとな何なのかということを私なりに解説したいと思います。このような考えに至ったのは、色々な状況があるにせよ Windows Froms などの UI 技術が広く使われているのと、XAML を初めて学ぼうとしたときに書籍を含めて、新しい情報が少ないと感じたからです。

2014/12に追記
XAML の詳細を学習するには、XAML Deep Dive for Windows & Windows Phone App Jump Start という動画を参考にするのも良いかもしれません。日本語の字幕はありませんが、英語の字幕がありますので、斜め読みでも XAML を使ったことがある人にとっては役に立つと考えられます。

XAML が登場した背景

XAML(eXtensible Application Markup Language)は、.NET Framework 3.0 によって提供された技術になります。
ClientTechnology2014

.NET Framework 3.0 は、Windows Vista と同時に提供されたフレームワークになります。この時に、UI を作るための技術として WPF(Windows Presentation Foundation) とワークフローを実現する技術として WF(Windows Workflow Foundation) も提供されました。WPF は、UI を定義するために XAML を採用しており、XAML が UI 技術と考えがちですが、名前にアプリケーションが含まれていることから WF でもワークフロー定義として XAML を採用していました(この採用は、限定的であり、XAMLでなくともワークフローを定義できました)。XAMLが、広範なアプリケーションで利用可能になるには、.NET Framework 4.0(System.XAML 名前空間が提供されました)になります。
追記:.NET Framework 3.0では、WPFとWFだけなくWCF(Windows Communication Foundatipon) と デジタル アイデンティティを管理する Windows CardSpace も含まれています。説明では、UI 技術として焦点を当てていますので、XAML に関係する技術として WPF と WF を取り上げています。

Windows Vista では、新しいエアロ テーマなどに代表されるように美しいグラフィックスを提供した OS となります。商業的に成功したと言えませんが、技術的には Windows XP と大きな違いが何か所もあります。代表的なものを以下に示します。

  • 新しいディスプレイ ドライバー モデル(WDDM-Windows Display Driver Model-)
  • デスクトップ ウィンドウ マネージャー(dwm)
  • ユーザー アカウント制御(UAC)
  • 64 ビット OS

Windows XP までのディスプレイ ドライバーは XPDM(Windows XP display Driver Model)と呼ばれており、Windows Vista 以降の WDDM との互換性はありません。新しディスプレイ ドライバーになったことで、ディスプレイ ドライバー レベルでの Direct 3D に対する新しいプログラミング モデルを提供できるようになりました。つまり、OS レベルで GPU の恩恵を受けられるようになったことを意味しますし、このためにデスクトップ ウィンドウ マネージャーにより コンポジションなどが意味を持ってきます。
Windows XP までは、GPU を活用するにはDirectX などを採用したアプリケーションのみに限定されており、広範なアプリケーションへ GPU を活用できる道を開いたのが Windows Vista から採用された WDDM になります。しかし、新しいドライバー モデルへの移行には、様々な障害がつきものです。その大きな一つが、ディスプレイ ドライバーの性能が向上しないというものです。この理由から、Windows Vista ではダブル バッファリングという技術を採用しました(これが、Windows Vistaは遅いと呼ばれた原因です)。ダブル バッファリングは、描画内容をメモリ上に展開してから、GPU などを使って一気に描画する技術ですから、スムーズな描画をするには大量のメモリがあった方が良いのは自明のことになります。しかし、Windows Vistaリリース当時のハードウェアでは、メモリ1GというPCがローエンドで販売されていましたし、メモリ4Gとなると高価格帯であるハイエンド機種のみとなっていたことも、商業的に成功しなかった理由であろうと私は考えています。しかし、Windows Vista によって64 ビット対応のドライバーの拡充であったり、UACへの対応であったりと、次の OS である Windows 7 に対するドライバーなどの整備が順調に進んだと言えるでしょう。当時のMacOS X は、32ビット カーネルのLeopardであり、限定的な 64 ビット対応をしていたと記憶しています。MacOS X と比べると、Windows OS は、64 ビット化へ道をビッグバンで進めてきたとも言えるでしょう。
Windows 7 になった時点で、WDDM は1.1 となり、ダブルバッファリングを廃止しました。もちろん、これだけではありませんが、様々な改良を経て、多くの方に使っていただける OS となりました。ここまでの説明で明らかなことは、Windows OSの描画機能が、OS レベルで Direct X をサポートするようになったのが Windows Vista 以降だということなのです。

一方で、Windows OS のグラフィカル ユーザー インターフェースはウィンドウが主体となっています。古くは、16 ビット時代の Windows 1.0 に始まった GDI(Graphics Design Interface)によるものであり、Windows 9x までは多くのコントロールなどを多用したアプリではリソース不足に悩まされたことが何度もありました。リソース不足は、Windows XP に代表される 32 ビット OS の時代では、お目にかかる機会も少なくなりましたが、一部のアプリケーションではテクニックによってリソース不足を解消していたと私は聞いています。つまり、GDI を採用した技術である Windows Forms などは、16ビット Windows 時代から慣れ親しんだ ウィンドウ ハンドル(hWnd)を使用する Win32 API との親和性が高いのです(ベースになっている技術が一緒だからです)。それでは、WPFのに代表される XAML を使った UI 技術はどうでしょうか? Windows Forms などの GDI とは、全くの別物と呼ぶことができます。私が別物と呼ぶ理由は、後で説明しますが、GPU を有効活用して GDI とは異なる新しい ユーザー体験を作るための技術が WPF だということになります。

今度は、アクセシビリティというか、表示の見易さという観点から 最新 OSである Windows 8.1 を考えてみます。Windows 8 では、ピクセル密度という考え方がデザイン ガイドとして導入されました。画面表示におけるスケーリングを、100%、140%、180%を自動的に行うというものです。たとえば、Surface Pro は10.6インチで1920x1080(フルHD)という解像度になります。このサイズだと、スケーリングが100%だと文字が小さ過ぎて、読み難い人もでてきます。このため、出荷時設定として文字サイズが150%になっていたりします(DPI)。Surface Proから理解できることは、解像度を向上させてもモニター サイズによっては、可読性を損なうことから、DPI設定を調整する必要があるということです。DPI 設定は、Windows 8.1 よりモニターごとに設定できるようになりました。Windows XP時代のDPI設定は再起動が必要でしたが、Windows 8.1ではサインオフだけで済みようになっています。DPI設定の改良は、Windows Vista でも実施されており、Windows 7 で更なる改良が実施され、Windows 8/8.1 で地道で改良がされているものの 1つになります。
アプリを高 DPI に対応しようとすると、それなりに工数がかかります。この点を、Windows Forms と WPF で解説した記事が、田中達彦さんのブログにありますので、読むことをお勧めします。
今年(2014年)に入って、4Kモニターの販売が始まりました。様々な記事で、4Kモニターの使用記事を読むことができますが、量販店などで販売されるいる PCやタブレットの解像度はフルHD サポートが一般化していると思います。解像度が向上すれば、表現できる領域が増えるので、アプリを作ったりする開発者にとっては良いことなのかも知れません(昔に、仕事でアプリの仕様を決めるのに、1024x768を前提としていたのが嘘のようです)。でも、5年後を想像してみてください。4Kモニターは、現在のところ安いもので10万円を切っていますが、5年後には価格はどうなっているでしょうか。また、ノートPCやタブレットPCの解像度もどうなっているでしょうか? アップルさんのRetainaに代表される高解像度がもたらしたものの一つに、スケーリングへの柔軟な対応というものがあります。これは、iPad Retaina やAndroid タブレットなどで顕著になってきています。これと同じことが、きっと PC というフォームファクターでも起きると私は考えています。皆さんは、どのように考えるでしょうか?先に紹介した田中達彦さんのブログを読めば、高DPI への対応が、以下のようになることが理解できます。

  • Windows Forms などの GDI 系のアプリは、アプリ側での対応が必要になる。
    対応しないと、文字が切れたりなどの表示上の不具合などが起きる可能性が高くなります。
  • WPF は、対応済みである(モニターごとの DPI 設定には、アプリ側の対応が必要)。
  • Windows ストア アプリは、スケーリングにはフル対応している。

ここまでの内容をまとめると、WPF は GPU を活用することを視野に入れて開発された UI 技術であること。そして、高 DPI への対応に迫られる可能性が高いということが言えます(解像度の向上などから避けられなくなっていくことでしょう)。

WPF という UI 技術とは

WPF と Windows Form では、考え方自体が異なります。顕著な例としては、ウィンドウ ハンドル(hWnd)の取り扱いにあると言えます。
hWndWindow

WPF の場合は、Window、もしくは NavigationWindow のみが ウィンドウ ハンドルを持ちます。言い換えると、GDI との接点を持ち、ウィンドウ内のコントロールはウィンドウ ハンドルを持ちません。一方で Windows Formsでは、Form だけでなく全てのコントロールがウィンドウ ハンドルを持ちます。つまり、WPF は、ウィンドウ ハンドルを使用しない方が良いとも言えます。ウィンドウの中に配置されるコントロールも、Windows Forms と同じ名前のものもありますが、異なる名前になっているものもあります。コントロールの対比としては、Windows フォーム コントロールおよび同等の WPF コントロールというドキュメントがあります。また、WPF はトップ レベルのウィンドウ以外のレンダリングには、GPU(DirectX 9以降)を使用します。この関係で、GPU を使用しないソフトウェア レンダリングもサポートしています。ソフトウェア レンダリングは、Windows XP では有効になっています(これは、最初に説明した通りディスプレイ ドライバーがWDDMではないからです)。ソフトウェア レンダリングか GPU レンダリングかは、WPFのランタイムが自動的に決定します。レンダリングを意識的に設定するには、レジストリを変更する必要があります。
Windows Vista 以降の WDDM 対応のドライバーでは、WPF は GPU レンダリングが行われることから、すべてのケースではないにしろ高速にレンダリングされる可能性が高くなります。これらの描画の違いから、良く言われるのが GDI と違い過ぎるという話です。

  • GDI 系では、同期的に描画される。
  • WPFでは、コンストラクター、Loaded の順に呼び出される。
  • Loaded は、自分自身のみで内部のコントロールが描画されているとは限らない。
    たとえば、Window_Loadedイベントで、Window内部に配置したコントロールが描画されているとは限らない。

これは、WPF の特徴的なもので、コンストラクターが呼び出されたことでクラスのインスタンスは作成されますが、実際の描画がされたことを意味しません。また、内部に配置したコントロールが描画されたことも意味しません。一方で、Windows FormsなどのForm_Loadedイベントであれば全てのコントロールが描画されたと考えても問題はありません。これは、WPFがオブジェクト インスタンスを作成してから、描画をエンジンへ依頼してエンジンが実際のレンダリングを行うまでの差と考えても良いものになります。このことから、描画を含めるとタイミングを取るのが難しいので、どうしたら良いでしょうかという質問を昔から頂きます。この答えは、Loadedイベントを待ってから、処理を続けるようにして下さいというものになります(たとえば、Silverlightではこの理由からJS側でLoadedを処理してから、フォーカスを移動するなどをしていました)。
ここまでの説明を読むと、WPF って何か面臭そうという認識を持った人もいらっしゃることでしょう。面倒臭さを乗り越えてまで、利用する価値があるのかなという疑問です。多分、使用する人によって感じるメリットは違うと思いますが、私が考えるメリットは以下のようなものになります。

  • 柔軟なレイアウト システム。
  • UI 定義とコードを完全に分離できる。
  • 柔軟なコントロールのコンテンツ モデル
  • UI オブジェクトの永続化。
  • アニメーションのサポート。
  • などなど。

柔軟なレイアウト システム

Windows Formsに代表される GDI 技術は、良くも悪くも座標位置を固定します。つまり、ウィンドウ サイズが変化したときに表示位置を調整しようとすれば、何らかのコードが必要になります。このことは、DPI設定が変更されると表示位置が崩れる原因になります。このため、WPFではフレキシブル レイアウトと固定レイアウトという概念が導入されています。フレキシブル レイアウトでは、利用するパネル コントロールによって、表示位置を柔軟に調整するようになっています。この顕著な例として、Width とHeight プロパティに「Auto」という値を設定できることを示します。Autoは何かと言えば、コントロールに設定した内容に応じてWidthやHeightを自動的に調整するというものです。これが意味することは、Width や Height プロパティに設定した値は、描画後に変化しないことを意味します。この理由から、ドキュメントで Width や Height を推奨値という表現をしており、コントロールの実際の大きさを取得するには ActualWidth と ActualHeight プロパティを使用します。一方で、Windows Formsでは、Size.Width や Size.Height プロパティは常に固定となります。また、コントロールの表示位置を表す左上の座標は、Windows Forms では Location.X や Location.Y プロパティとなりますが、WPF では利用する パネル コントロールによって異なることになります。たとえば、Windows Forms のように固定座標にするために Canvas コントロールを利用すると、Canvas.Top と Canvas.Left 添付プロパティになり、Grid コントロールを利用する場合は、Margin プロパティになります。このような違いは、フレキシブル レイアウトか固定レイアウトのどちらを採用するかによって変化します。それでも、解像度が向上すればするほど、フレキシブル レイアウトを採用した方がユーザーにとって便利だと私は考えます。なぜなら、ユーザーにとって使い易いサイズとは、ユーザーごとに違うものだからです。

UI 定義とコードを完全に分離できる

パーシャル クラスが提供されるまで、Windows Formsでは UI 定義とイベント コードなどを分離することはできませんでした。WPF では、UI 定義を XAML という XML で定義し、イベント コードはコード ファイルに記述することで、完全に分離されています。このことは、UI 定義用の XAML のみをデータ ファイルとして提供できることも意味します。つまり、プログラムを再ビルドすることなく、XAMLというデータ ファイルを変更することで UI レイアウトを変更できるプログラムを容易に実現すできることになります。また、UI 定義を XAML という XML 形式で記述できるということは、WPF のオブジェクトは XAML との間で容易にシリアライズできることを意味しています。Windows Forms のコントロールは、シリアライズが容易にできないので、シリアライズしようと考えるのであれば、独自に作りこむ必要があります。一方で、XAML が記述するのが面倒という話を良く聞きます。これは、XAML を使ったデザイナー サポート機能が Visual Studio で貧弱だったことが一因です。
XAML のデザイナー サポートは、Visual Studio 2008 から始まりました(ベータという意味では、Visual Studio 2005からです)。この当時は、XAMLによるデザイン ツールとして Expression Blendというデザイナー向け製品がありました。そして、Visual Studio 2010のデザイナーが向上したと言っても、Expression Blend を使った方が柔軟なデザインができることには変更はありませんでした。これが、Visual Studio 2012になると、Expression Blend との統合が行われて、Visual Studio 2012 にExpression Blend が同梱されるようになりました(WPF で Blendが使用できるには、Visual Studio Update を待つ必要がありましたが)。つまり、Visual Studio 2012からは、XAML を編集するのに Expression Blend という製品を購入する必要がなくなったのです。Visual Studio 2012 への Expression Blend の統合によって、柔軟な XAML デザインをできるようになっていますし、XAML を使ったユーザー コントロールの作成などは Expression Blend を使うことで GUI のみでできるようになりました。
追記:実は、Visual Studio 2010から IDE 自体が WPF化されています。Visual Studio 2012では、IDEの動きが Visual Studio 2010 よりも高速化されています。Visual Studio という IDEにおいては、Visual Studio 2008 から Managed Package という機能拡張がなされていまして、WPF などとの統合がしやすい環境が整備されてきています。つまり、Visual Studio 2012/2013 が高速に動作するという事実からも、WPFが遅い描画技術ではないことも理解して頂けることでしょう。

柔軟なコントロールのコンテンツ モデル

Windows Forms のコントロールが持つプロパティとの大きな違いとして、WPF コントロールが持つコンテンツ モデルがあります。たとえば、Windows Forms の Form コントロールでは疑似的にコントロール 配列を扱うために Controls プロパティを持っています。これが、WPF では Window オブジェクトでは Content プロパティであり、Canvas や Grid コントロールでは Children プロパティになっています。Content プロパティは、1つの子要素(コントロール)を意味しており、Children プロパティがコントロール コレクションを意味します。これらを総称して、コンテンツ モデルと呼んでいます。XAML で Content と言った場合に設定できるものは、Object 型のオブジェクトになります。つまり、パネル コントロールでも良いし、Image オブジェクトでも良いし、要はどんなオブジェクトでも設定できることを意味します。たとえば、Windows Forms の Button コントロールは Image プロパティを使ってイメージを設定できますが、WPF の Button コントロールは Content プロパティしかありませんから、Content に Image オブジェクトを設定すれば同じことができますし、パネル コントロールを使えば Imageだけでなく、様々なコントロールをボタンの中に設定することも可能になります。
また、XAMLには強力なスタイル機能があり、スタイルを切り替えるだけでコントロールの見え方を変更することが可能になっています。Windows Forms でユーザー コントロールを使ってオーナー ドローを使ってオリジナルの外観を持つコントロールを作る必要性は、WPFにはありません。

UI オブジェクトの永続化

既に説明したように WPF では、UI 定義を XAML という XML 形式で記述します。この XML 形式が、WPF オブジェクトのシリアライズを行う形式ともなっています。ユーザー コントロールやカスタム コントロールを容易に作成できるようにするために、WPF では依存関係プロパティ(Dependency Property)システムが用意されています。これは、.NET Framework のリフレクションだと、高価な実行コストがかかりますが、WPF に最適化した形でリフレクションを実現する仕組みと考えれば良いでしょう。独自に作成したプロパティを依存関係プロパティとすることで、容易に XAML という XML 形式に表現できるようになっています。この依存関係プロパティを使って、添付プロパティも作成されており、添付プロパティを使ってビヘイビアという使い方(コーディング レスで振る舞いを定義します)もできるようになっています。

アニメーションのサポート

提供するアプリが複雑になればなるほど、アプリの使い方をユーザーが気付くようにすることは重要です。このような用途で、アニメーションを利用することができます。WPF で用意されているアニメーションは、アニメーションを実現するためだけのメカニズムであって、組み込みで用意されている アニメーション ライブラリは非常に限定的となっています。この理由は、WPF が提供された当時では、ユーザー エクスペリエンスにおける統一的なアニメーションの解釈方法が決まっていなかったからです。

他にも XAML ならではの機能として、データ バインディングがあります。XAML のデータ バインディングには、次の3種類があります。

  • 一回限り
    バインディングしてから、データの変更は起きない場合
  • 一方向
    データからコントロールへの一方向
  • 双方向
    データとコントロールの双方向であり、コントロールがフォーカスを失うとデータが変更される

このような強力なデータ バインディングが用意されており、データ バインディングをより有効に活用するためのデザイン パターンとしてMVVM(Model View ViewModel) などの使用が推奨されています。MVVMの使用は必須というわけではありませんが、利用できるのであればデータバインディングを有効活用するためにも利用するようにした方が良いでしょう。

サード パーティ製のコントロール

WPF が提供された当時は、サード パーティ製のコントロールも貧弱でした。でも、現在はサード パーティ製のコントロールも充実しています。

WPF コントロールのコンテンツ モデルは、とても強力です。ですから、自分でカスタム コントロールを作成することもできます。独自にコントロールを作成する場合の学習には、WPF Toolkit が役立つことでしょう。WPF Toolkit は、マイクロソフトが提供している オープン ソースのソフトウェアで、WPF が提供された当時のコントロール不足を補う目的とカスタム コントロールを作り方のヒントを提供するためのものです。説明した市販のコントロールは、日本で代表的なものだけとなります。海外で販売されているものも含めれば、Windows Forms と遜色がないサード パーティ製のコントロールが市販されています。サード パーティ製のコントロールを使用するかどうかは、カスタム コントロールを作成する労力とコストを比較して考えれば良いでしょう。

 

GDI 技術とは全くことなる技術である WPF を今から学習するには、どうしたら良いでしょうか。私の場合は、.NET Framework 3.0 の頃から使用していますし、もう覚えてしまっているので、これから学習する人にどのように説明したら良いのかを考えてみたいと思います。私が、最初にお勧めしたいのは「プログラミング Windows 第6版」という書籍です。
pgm_windows6_J

この書籍は、俗に言うペゾルド本であり、Windows プログラミングを学ぶ時の王道のような書籍です。私も、Windows 3.1の頃に読んで GDI を使った Windows プログラミングを勉強しました。昨年に発売した第6版は、Windows ストア アプリ、つまり Windows Runtime と XAML になっています。Windows Runtime XAML(以下、WinRT XAML と略します)は、WPF の XAML とは微妙に異なる箇所がありますが、XAML としての文法などを学習するには、きっと役立つことでしょう。

最後に、XAML による Presentation 技術で私が良く聞かれる質問として、「なぜ、同じ XAML なのに挙動が違うのですか?」というものがあります。この答えは、マイクロソフトは複数の XAML 用のレンダリング エンジンを持っているからですというものになります。具体的には、WPF、Silverlight、Windows Phone、Windows ストア アプリという4種類のレンダリング エンジンがあり、フル機能は WPF ですが、Silverlight の発展形として Windows Phone と Windows ストア アプリがあり、様々なフィードバックから一部の機能は Silverlight、Windows Phone、Windows ストア アプリの方が WPF よりも使い易くなっていることから、構文を含めて微妙な違いを生んでいます。どの XAML レンダリング 技術を使ったとしても、完璧ということはなく、用途によっては GDI の方がパフォーマンスが良くなる場合もあることでしょう。WPF に代表される XAML という Presentation 技術は、2D を含めてビデオやドキュメントなどの様々なメディアを統合してユーザー体験を向上させることを目的にしています。3D を使ったパフォーマンスが良いアプリを作成するのであれば、DirectX を使用した方が良いのは自明のことです。あくまでも、ユーザー体験を実現するための技術が、XAML という Presentation 技術の本質となります。

Comments (0)

Skip to main content