Windows 8.1 のグリッド アプリケーションについて
Visual Studio 2013で提供する Windows ストア アプリ用のプロジェクトテンプレートには、次の4種類があります。
- 新しいアプリケーション
- グリッド アプリケーション
- ハブ アプリ
- 分割アプリケーション
Visual Studio 2012のプロジェクトテンプレートと比較すると、ハブ アプリが新しく追加されています。ハブ アプリは、Windows 8.1 で追加された Hub コントロールを使用したアプリの作り方を示すものです。表面的には、グリッド アプリケーションと分割アプリケーションが提供する機能としては、スナップ時のレイアウトを別にすればVisual Studio 2012のものと同じと考えることができます。でも、内部的には、大きな変更がなされています。グリッド アプリケーションで作成されるページの構造を以下に示します(この構造は、ハブ アプリや分割アプリケーションでも同じです)。
クラス図では、Pageクラスの継承関係と相互作用だけに焦点を当てています。ObservalDictionaryはIObservableMap<string, object> を継承していますし、NavigationHelperはDependencyObjectを継承しています(クラス図では、ステレオタイプで表現しています)。各ページが、Pageクラスを継承しているので、Visual Studio 2012の時のようにビルドしなくてもVisual Studioのデザインビューを表示することができるようになっています。プロジェクトのCommonフォルダーに作成されているコードファイルは、次のようになります。
ファイル名 | 説 明 |
NavigationHelper.cs | Visual Studio 2012のLayoutAwareクラスで定義されていた機能が含まれています。 |
ObservableCollection.cs | Visual Studio 2012のLayoutAwareクラスのインナークラスとして定義されていたクラスです。 |
RelayCommand.cs | 新しく追加されたコードで、XAMLのコマンドパターンで使用します。具体的には、戻るボタンで使用しています。 |
SuspensionManager.cs | Visual Studio 2012 と同じものです。 |
最初にSuspensionManagerクラスは特に変更はありませんので、App.xaml.csのOnLaunchedイベントでRegisterFrameメソッドを使ってFrameオブジェクトのインスタンスを登録するのも同じです。RegisterFrameメソッドで登録しないと、ナビゲーション履歴やセッション情報が一時停止時に保存されませんのでご注意ください(言い換えれば、OnSuspendingイベントでSuspensionManagerのSaveAsyncメソッドを呼び出すということです)。
NavigationHelperクラスの使用方法
次に各ページで、NavigationHelperクラスをどのように使用しているかを説明します。ちなみに、NavigationHelperの先頭にコメントで、使用方法が記述されています。
- フィールド定義
navigationHelper と defaultViewModel を定義しています。 - プロパティ定義
NavigationHelper と DefaultViewModel を定義しています。NavigationHelperプロパティを使って、戻るボタンにコマンド パターンを使用している点に注意してください。 - コンストラクタ
NavigationHelperクラスのインスタンスを作成して、NavigationHelper.LoadStateデリゲートの登録を行います。ページ毎のセッションを保存する場合は、NavigationHelper.SaveStateデリゲートの登録を行う必要があります。 - イベントハンドラー定義
PageクラスのOnNavigatedFrom と OnNavigatedToイベントハンドラーで、NavigationHelperの OnNavigatedTo と OnNavigatedFromメソッドを呼び出します。このメソッド呼び出しを記述しないと、LoadStateとSaveStateデリゲートが呼び出されなくなるので必ず記述します。 - デリゲート定義
NavigationHelperのLoadState と SaveStateデリゲートに登録したメソッドを定義します。LoadStateデリゲートは、ビューモデルなどを使ってデータソースの初期化を行ったり、ページ毎のセッションを復元したりします。SaveStateデリゲートは、ページ毎のセッションを保存するロジックを記述します。
SaveStateデリゲートは、SuspensionManagerクラスにFrameオブジェクトを登録していないと呼び出されないことに注意してください。
NavigationHelperクラス
今度は、NavigationHelperクラスがどのようになっているかの説明を示します。
メソッド、プロパティ名 | 説 明 |
コンストラクタ | キーボードとマウスを使ったナビゲーションをサポートするためのイベントハンドラーを登録しています。 |
CoreDispatcher_AcceleratorKeyActivated | キーボードを使ったナビゲーションを実装します。具体的には、ALTキーと矢印キーの組み合わせで、ページを進めたり戻ったりします。 |
CoreWindow_PointerPressed | マウスのボタンを使ったナビゲーションを実装します。具体的には、マウスによってブラウザーの進むボタンや戻るボタンを使ったナビゲーションです。 |
GoBackCommandプロパティ | RelayCommandクラスを使用して、XAMLのコマンドパターンで使用するコマンドオブジェクトのインスタンスを返します。このプロパティが、戻るボタンで実行されるコマンドとなります。 |
GoForwardCommandプロパティ | RelayCommandクラスを使用して、XAMLのコマンドパターンで使用するコマンドオブジェクトのインスタンスを返します。このプロパティが、ページを進めるときに呼び出されるコマンドとなります。 |
CanGoBack CanGoForward GoBack GoForward | Frameオブジェクトを使ったナビゲーションのためのメソッドです。 |
OnNavigatedTo OnNavigatedFrom | プロセス継続時間管理として、Frameオブジェクトを使ったナビゲーションに応じてページ毎のセッションを保存したり、LoadStateデリゲートを呼び出すためのメソッドです。 |
NavigationHelperクラスの内容を見れば、Visual Studio 2012のLayoutAwareクラスのナビゲーション サポートとプロセス継続時間管理の機能を持っていることを理解できます。異なるのは、継承関係を使用しなくなったことと、XAMLのコマンドパターンを使用して戻るボタンのコマンドオブジェクトを用意していることになります。そして、NavigationHelperクラスがDependencyObjectを継承している理由は、コマンドオブジェクトをXAMLのデータバインディングで記述できるようにするためになります。
SampleDataSourceクラス
SampleDataSourceクラスも、Visual Studio 2013で大きく変更されたクラスになります。プロジェクトのDataフォルダーに作成されているファイルを示します。
ファイル名 | 説明 |
SanpmeDataSource,cs | データソースに必要となるクラスを定義するファイルです。 |
SampleDataSource.json | データソースのサンプルデータを定義するJSON形式のファイルです。 |
Visual Studio 2012と比較すると、次に示すような箇所が変更になっています。
- BindableBase クラスが削除された。
- SampleDataGroup クラスとSampleDataItemの循環参照が無くなった。
- SampleDataSourceクラスは、大幅な見直しが行われている。
シングルトンパターンで実装されているのは一緒ですが、サンプルデータをjson形式のファイルから読み込んだりと提供するメソッドが、大幅に変更されています。
ビューモデルを作り易くするという観点で言えば、BindableBaseクラスが提供されなくなったのが残念だと私は考えます。もちろん、自前でINotifyPropertyChangedインターフェースを実装しやすくする仕組みを用意すれば構わないのです。特に、XAMLのバインディングを考えた場合に変更通知を実装するのは必須ですから、ObservableCollectionだけでなくINotifyPropertyChangedインターフェースも前提にビューモデルを考えなければなりません。
ビュー、データテンプレート、etc
Visual Studio 2013のプロジェクトが、Visual Studio 2012のプロジェクトと大きく変化した箇所として Commonフォルダーで提供していたStandardStyles.xamlというスタイル定義の廃止があります。StandardStyles.xamlでは、テキストのスタイルに始まり、アプリバーの各種スタイル、GridViewやListViewのデータテンプレートなど、非常に多くのスタイルが定義されていました。これらのスタイル定義が、Visual Studio 2013では無くなっているのです。無くなったことで、どのように変更が必要かを記載します。
- アプリバーは、AppBarButton、AppBarToggleButtonクラスのIconプロパティとLabelプロパティで簡単に設定できるようになった。
- データテンプレートは、各アプリごとのページリソースとして定義されるようになった。データテンプレートの編集をページ毎に行う必要がある。
- テキストのスタイルは、generic.xaml(Windows Kitで提供される)で定義されるHeaderTextBlockStyle、SubheaderTextBlockStyleなどを使用するようになった。個別にスタイルを定義したい場合は、アプリリソースなどで定義する必要がある。
- 戻るボタンのスタイルが無くなり、AppBarButtonを利用するようになった。
ビューの切り替えについては、分割アプリケーションを除けばVisualStateManagerを使用した方法を利用しなくなりました。これは、新しいウィンドウ化モードのサポートに伴って固定サイズのスナップビュー(横幅が320ピクセル)が廃止されたことに伴うものです。もちろん、コンテンツによってはビューの切り替えをサポートした方が良いので、この場合は分割アプリケーションのVisualStateManagerの使用方法が参考になると思います。
Visual Studioが提供するプロジェクト テンプレートを使用すると同じデザインのアプリばかりになると指摘する方もいらっしゃいますが、私はそのようには考えておりません。ページナビゲーションであったり、基本的なページデザイン(余白であったり、フォントサイズであったり)などを学習することに役立つからです。何よりも、Windows ストア アプリはコンテンツ中心のアプリですから、デザインを自分で定義するのは当たり前のことであり、デザインを変更しないから同じ見た目のアプリになるだけのことが批判されているのだと考えるからです。要は、デザインを自分のアプリらしく設計しましょうというのが、私の主張です。事実、マイクロソフトが提供している開発体験テンプレートも同じプロジェクト テンプレートを使用していても、デザインは様々なものになっていますよね。つまり、アプリが提供するコンテンツを一番良いと思われる方法で提供するデザインにするところまでが、アプリの一部だということなのです。
ここで解説したプロジェクトの構造は、Visual Studio 2013ではグリッド アプリケーション、分割アプリケーション、ハブ アプリケーションに当てはまりますし、アイテム テンプレートのほとんどにも当てはまりますので、理解しておくことでVisual Studioのアイテム テンプレートを有効活用するのに役立つはずです。このエントリーで解説しない機能については、グリッドアプリケーションのドキュメントで公開したドキュメントをご参照ください。Visual Studio 2012ベースのドキュメントですが、きっと役に立つはずです。