TIPS自作のユーザー・コントロールに独自のプロパティを実装し、そこにデータ・バインドする方法を解説する。Insider.NET連載目次UserControlクラス(Windows.UI.Xaml.Controls名前空間)を継承したコントロール(以降、ユーザー・コントロール)を作り、それにデータ・バインドしたいことがある。本稿では、その方法を解説する。8版)」からダウンロードできる。8)アプリは割愛するが、考え方は同じである。2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。問題ユーザー・コントロールの中でもデータ・コンテキストが使えるので、それをバインドするのならば簡単だ。それでは汎用性に欠けるという問題がある。汎用的なユーザー・コントロールとするためには、利用するページの側でユーザー・コントロールのプロパティに明示的にバインドできる必要がある。本稿では、まずユーザー・コントロールの中でデータ・コンテキストを利用する方法を示し、それからバインド可能なプロパティを実装する方法を解説する。ユーザー・コントロールのデータ・コンテキストユーザー・コントロールにも、それが属するビジュアル・ツリーのデータ・コンテキストが適用される。ユーザー・コントロールの中でもデータ・コンテキストを利用できるのだ。ページのデータ・コンテキストにDefaultViewModelプロパティが設定されており*1、その「URLs」キーにはURL文字列のコレクションが設定されているとする(次のコード)。SubページのDefaultViewModelに「URLs」をキーとしてURL文字列のコレクションをセットする(上:C#、下:VB)上はLayoutAwarePageクラスを継承した場合である。継承しない場合は、DefaultViewModelプロパティの実装を独自に行ったうえで、OnNavigatedToメソッドでセットする。すると、このページに配置して利用するユーザー・コントロールでは、「URLs」をキーとして上のコードの3つのURL文字列をバインドできる。コントロール]を選択してMyUserControl1.xamlファイルを作成した後に、上記のコードを記述する。DataTemplateを、一度にお見せできるようにGridViewコントロールの内部に記述しているが、ページやApp.xamlファイルのリソースとして記述してもよい。作成したユーザー・コントロールは通常のコントロールと同様に使用できる。このユーザー・コントロールにもページのデータ・コンテキスト(=DefaultViewModelプロパティ)が適用される。すると、内部のGridViewコントロールのItemsSourceプロパティには、DefaultViewModelプロパティが持っているデータの中から「URLs」というキーで識別されるデータ、すなわちURL文字列のコレクションがバインドされることになる。いうことは、GridViewコントロールの各アイテムにはそれぞれのURL文字列がバインドされるので、データ・テンプレートの中でパスを指定せずにただ「{Binding}」と記述しているところでは、URL文字列がバインドされることになる。以上のように、ユーザー・コントロールにもページのデータ・コンテキストが伝播(でんぱ)されることを利用すれば簡単にバインドできる。この方法では汎用性に欠ける。データ・コンテキストの内容が違うページでは利用できないからだ。逆にいえば、データ・コンテキストの内容が違うページでも、ページの側でバインドするデータを設定できれば、汎用的に利用できる。そのためには、ユーザー・コントロールのプロパティにバインドできればよい(次項)。ユーザー・コントロールのプロパティをバインド可能にするには?コントロールのプロパティを「依存関係プロパティ」として実装すればよい。ここでは例として、WebViewコントロール(Windows.UI.Xaml.Controls名前空間)をラップしたユーザー・コントロールを作ってみよう。ユーザー・コントロールとして仕立てる意味としては、Webページが表示されるまでの待ち時間にプログレス・リングを出しておきたいものとする。2012でWindowsストア・アプリのプロジェクトを作成し、続いてメニューバーから[プロジェクト]−[新しい項目の追加]を選択する。コントロール]を選んでユーザー・コントロールをプロジェクトに追加し、「WebViewWithProgressRing.xaml」という名前を付けておく。次に、作成した「WebViewWithProgressRing.xaml」ファイルに、ProgressRingコントロール(Windows.UI.Xaml.Controls名前空間)とWebViewコントロールを配置する(次のコード)。/></Grid></UserControl>ユーザー・コントロールにProgressRingコントロールとWebViewコントロールを配置した(XAML)先頭のUserControlタグ内にあるx:Class属性とxmlns:local属性の値は、プロジェクトの名前空間が入っているので、場合によって異なる。このユーザー・コントロールを利用する側からは、UriオブジェクトをコントロールのSourceプロパティにバインドしてもらうことにしよう。このSourceプロパティは、普通のプロパティではなく依存関係プロパティとして実装する。コードビハインドの「WebViewWithProgressRing.xaml.cs/.vb」ファイルに、次のようにコードを追加する。SubWebViewWithProgressRingクラスに依存関係プロパティを追加した(上:C#、下:VB)上のコードで、DependencyProperty型の静的メンバ「SourceProperty」が、依存関係プロパティの本体だ。データ・バインディングではなくコードから直接プロパティを操作するために、Uri型のSourceプロパティも必要だ。Sourceプロパティは、SourceProperty依存関係プロパティをラップするように記述する。今回はSourceProperty依存関係プロパティに値がセットされたときにメソッドを呼び出したいので、DependencyProperty.Registerメソッドの第4引数でOnSourceChangedメソッドが呼び出されるように登録している。このOnSourceChangedメソッドでは、ユーザー・コントロールに置いたWebViewコントロールを隠した上で新しいページへのアクセスを開始させるとともに、ProgressRingをアクティブにする。WebViewコントロールがロードを完了した時点で、逆にWebViewコントロールを表示し、ProgressRingを止める(次のコード)。ClassWebViewWithProgressRingクラスの完成形(上:C#、下:VB)これで、WebViewWithProgressRingユーザー・コントロールのSourceプロパティにWebページのUriをセットすると、まずプログレス・リングが表示され、Webページのロードが終わるとWebViewコントロールの表示に切り替わるようになる。最後に、完成したユーザー・コントロールをページに配置してみよう。次のXAMLコードのように記述できる。ResourceKey="WebViewGridDataTemplate"/></GridView.ItemTemplate></GridView>WebViewWithProgressRingユーザー・コントロールをページに配置した(XAML)DataTemplateを、一度にお見せできるようにGridViewコントロールの内部に記述しているが、ページやApp.xamlファイルのリソースとして記述してもよい。ここでも本稿の冒頭に示した例と同様に、ページのDefaultViewModelに「URLs」をキーとしてURL文字列のコレクションがセットされているものとする。すると、上のコードのGridViewコントロールのItemsSourceプロパティにはURL文字列のコレクションがバインドされ、GridViewコントロールの各アイテムのDataTemplateに配置されたWebViewWithProgressRingコントロールのSourceプロパティにはURL文字列がバインドされる。URL文字列をUri型の依存関係プロパティにバインドする場合、バインディング・エンジンが自動的に文字列からUriオブジェクトへ変換してくれる(バリュー・コンバータは不要)。最後に、コードビハインドに冒頭で示した「ページのDefaultViewModelに“URLs”をキーとしてURL文字列のコレクションをセットする」コードを追加すれば完成だ。実行してみると、次の画像のようにWebページが表示されるまでプログレス・リングが表示される。Webページが表示されるまでの間、プログレス・リングが回転しているまとめバインディング・ソースとなるプロパティにはINotifyPropertyChangedインターフェイス(System.ComponentModel名前空間)の実装が必要であった*2。バインディング・ターゲットのプロパティは、依存関係プロパティでなければならない。これでデータ・バインディングのソースとターゲットの両方を理解できた。依存関係プロパティについて詳しくは次のドキュメントを参照してほしい。