8]CollectionViewSourceクラスを使って、複数のコントロール間で選択されている項目を同期する方法を説明する。Windowsストア・アプリでよくあるケースは、通常のビューではGridViewコントロールを表示し、スナップ・ビューのときはListViewコントロールに切り替える場合だ。この場合には、ビューを切り替えても同じ項目が選択されているべきである。本稿では、コレクションをコントロールにバインドして表示する場合に、CollectionViewSourceクラスを利用して、そのような選択の同期を実現する方法を説明する。8版)」からダウンロードできる。8)アプリで共通である。2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。8.0(無償)が必要となる。●選択が同期しないアプリ普通のコレクションをバインドしただけでは、複数のコントロール間で選択された項目が同期することはない。それを確認するためのアプリをまず作ってみよう。8]」で作ったSampleDataCollectionクラスをそのまま使うことにしよう。これはSampleDataというクラスのオブジェクトを格納しているコレクションで、SampleDataクラスは文字列型のTitleプロパティとUrlプロパティを持っている。次に、ユーザーが選択できるコントロールを複数配置した画面を用意する(次のコード)。Windowsストア・アプリにはComboBoxコントロールと2つのListBoxコントロールを配置した。8アプリはComboBoxコントロールが利用できないので、2つのListBoxコントロールだけを配置した。それらのコントロールを収めたGridコントロール(名称は「grid1」)のDataContextプロパティに、前述したSampleDataCollectionクラスのオブジェクトが実行時にセットされるものとして、データ・バインディングを設定してある。デザイン時にもデータが表示されるようにした*1。Windowsストア・アプリ用のコードを示す。8アプリの画面にユーザーが選択できるコントロールを複数配置する(XAML)ComboBoxコントロールがない以外は、基本的にWindowsストア・アプリ版と同じである。ページの開始タグ内にある「xmlns:local=......」に記述する名前空間は、適宜改めてほしい。8]」を参照してほしい。上記のコードでは、「d:」接頭辞を使って、GridコントロールのDataContextプロパティにデザイン時のみSampleDataCollectionオブジェクトが設定されるようにしている。コードビハインドからデータ・コンテキストを設定しない限り、実行時にはデータが表示されない。8]」で行ったのと同様に、コードビハインドでSampleDataCollectionオブジェクトを作成してGridコントロールのDataContextプロパティにセットする(次のコード)。SampleDataCollectionをDataContextに与えれば表示される。各コントロールでは項目をバラバラに選択できてしまう。SampleDataCollectionをDataContextに与えれば表示される。各コントロールでは項目をバラバラに選択できてしまう。sampleCollectionSampleDataCollectionオブジェクトを作成してGridコントロールのDataContextプロパティにセットする(上:C#、下:VB)このコードは、Windowsストア・アプリではLoadStateメソッド(LayoutAwarePageクラスを継承してページを作った場合)、またはOnNavigatedToメソッド(Pageクラスを直接継承してページを作った場合)に記述する。8では、コンストラクタの末尾に追記すればよい。これで実行してみよう。コントロールごとに異なる項目が選択できるはずだ(次の画像)。選択の同期が取れていないということだ。8)●選択を同期させるにどうしたらよいだろう?一案としては、コントロールのSelectionChangedイベントで、ほかのコントロールの選択を変更してやれば、全てのコントロールで同じ項目が常に選択されるようにできるだろう。上記のWindowsストア・アプリでは、3つのイベント・ハンドラごとに、ほかの2つのコントロールを制御するコードを書かねばならない。面倒なうえに間違いも入り込みやすいだろう。データ・バインディングを使っているのだから、双方向バインディングを使ってユーザーの選択をほかのコントロールに伝播(でんぱ)させるようにすれば、きれいに作れそうだ。8のコードのみ掲載する)。/>......省略......コントロール同士を直接バインドしても実現可能(XAML)このコードは、以降では使わない。順を追ってコードを試している場合は、動作を確認できたら元に戻しておいてほしい。これでは、コントロールごとにバインディングの指定を記述するのがやはり面倒だし、変更があってバインディング・ソース(上のコードでは「comboBox1」コントロール)を削除することになった場合には全てのバインディング指定を書き直さねばならない。次に述べるように、もっと簡単に双方向バインディングによる選択の同期を実現できる方法があるのだ。●CollectionViewSourceクラスそのような目的に利用できるのがICollectionViewインターフェイス(Windows.UI.Xaml.Data名前空間)だ。ICollectionViewインターフェイスには、現在選択されている項目を表すCurrentItemプロパティやCurrentPositionプロパティがあり、それが変わったときに発火するイベントもある。ICollectionViewインターフェイスの実装を持つクラスが用意されている。8ではSystem.Windows.Data名前空間)である。CollectionViewSourceクラスをバインディング・ソースに使うと、コレクションをバインドするだけでなく、選択されている項目もバインドできるのだ。うれしいことには、コレクションを表示するために用意されているListBoxコントロールなどは、選択されている項目のバインドを自動的に行ってくれる。次で説明するように、コントロールのItemsSourceプロパティにCollectionViewSourceオブジェクトをバインドするだけでよいのだ。●選択を同期するには?バインドするコレクションを上記のCollectionViewSourceクラスにすればよい。具体的には、CollectionViewSourceクラスのインスタンスを作り、バインドしたいコレクションをそのSourceプロパティにセットして使うだけだ。コードビハインドでもXAMLコードでも書けるが、ここではコードビハインドでやってみよう。次に示すコードのように、とても簡単だ。SampleDataCollectionをDataContextに与えれば表示される。各コントロールでは項目をバラバラに選択できてしまう。DataContextに与えるコレクションをCollectionViewSourceでラップする。SampleDataCollectionをDataContextに与えれば表示される。各コントロールでは項目をバラバラに選択できてしまう。DataContextに与えるコレクションをCollectionViewSourceでラップする。8では、ファイル冒頭でSystem.Windows.Data名前空間を取り込む必要がある。実行して、どのコントロールの選択を変えても残りのコントロールの選択が同期して変化することを確認してほしい(次の画像)。8)Windowsストア・アプリ版のComboBoxコントロールでは、開いた状態のままカーソルキーで選択を変えてもほかのListBoxコントロールの選択が同期する。(XAML)」では、自動生成されたXAMLコードでCollectionViewSourceクラスが使われている。具体的には、自動生成されたXAMLコードの冒頭付近にPage.Resources要素があって、その中でCollectionViewSourceオブジェクトを生成している。それをページ内のコントロールにバインドして使っている。このようにすることで、スナップ・ビューに切り替えても選択している項目が変わらないようにしてあるのだ。●まとめCollectionViewSourceクラスを使うと、複数のコントロール間で選択されている項目を同期できる。これは、Windowsストア・アプリのプロジェクト・テンプレートでも多用されている。CollectionViewSourceクラスの詳細については、次のドキュメントを参照してほしい。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。