ナビゲーション モデル (C#/VB/C++ と XAML を使用)

ハブ アプリ、グリッド アプリ、スプリット アプリの各プロジェクト テンプレートで使われているナビゲーション モデルは、XAML を使って構築される Windows ストア アプリにお勧めのナビゲーション モデルです。このモデルでは、既定のウィンドウのコンテンツとして中央のフレームを作成し、ユーザーはそのフレームを使って他のページに移動します。 単一フレーム ナビゲーション モデルでは、アプリのようにスムーズにページを切り替えることができます。また、プログラムの状態の管理が簡単になります。 ナビゲーションついての詳しい情報と、XAML を使って構築される Windows ストア アプリの組み込みのナビゲーションを使った例については、「クイックスタート: ページ間のナビゲーション」をご覧ください。

重要  このトピックに記載の情報は、Microsoft Visual Studio 2013 に合わせて更新されています。

ファイル App.xaml.cs/vb/cpp では、Frame を作成し (まだ存在していない場合)、その Frame を現在のウィンドウのコンテンツにします。 フレームのコンテンツが null の場合、アプリは、コード ビハインド App.xaml で指定されているように、ホーム ページに移動します。たとえば、グリッド アプリケーションの場合、コードは rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups") ) となります。

セットアップ中に、SuspensionManager によって、Frame が登録されます。 SuspensionManager は、グリッド アプリケーション テンプレートまたは分割アプリケーション テンプレートで共通フォルダーに含まれるヘルパー クラスです。アプリが終了したときの状態の格納と読み込みを行うために使う実装を提供します。

すべてのアプリは、オペレーティング システムによって決定されるアプリのライフサイクルに従います。 リソースの制約、シャットダウン、再起動などの理由により、アプリがシステムによって終了された場合、開発者はアプリの再開時にデータを復元する必要があります。 SuspensionManager は、このタスクをサポートするために提供されます。

SuspensionManager では、アプリのプロセス ライフタイム管理を簡略化するために、グローバル セッション状態をキャプチャします。 セッション状態は、さまざまな条件で自動的にクリアされます。また、セッション間での伝達に便利な情報を格納するためにのみ使う必要があります。ただし、アプリがクラッシュした場合や、アップグレードされた場合は、破棄する必要があります。 これには、基本的に、一時的な UI データが含まれます。

SuspensionManager には、SessionState と KnownTypes という 2 つのプロパティがあります。

  • SessionState は、現在のセッションに対してグローバル セッション状態へのアクセスを提供します。 この状態は、SaveAsync メソッドによってシリアル化され、RestoreAsync メソッドによって復元されます。 すべてのデータは、DataContractSerialization を使って保存および復元し、できるだけコンパクトにする必要があります。 文字列には他の自己完結型のデータ型を使うことを強くお勧めします。
  • KnownTypes には、セッション状態を読み書きする際に SaveAsync と RestoreAsync メソッドによって使われる DataContractSerializer に提供されたカスタム型の一覧が格納されます。 最初は空ですが、型を追加して、シリアル化プロセスをカスタマイズできます。

SuspensionManager は、ディクショナリに状態を格納します (SessionState)。 ディクショナリには、Frame に一意にバインドされているキーに対する FrameState が格納されます。 各 FrameState ディクショナリには、その特定のフレームのナビゲーション状態における各ページの状態が保持されます。 ページごとに、ナビゲーション パラメーターと、ユーザーが追加することにしたその他の状態が格納されます。

これは次のようなしくみになっています。Frame が作成されたときに、状態をそのフレームに格納する必要がある場合は、すぐに登録する必要があります。 これらは、次の呼び出し ((SuspensionManager.RegisterFrame(rootFrame, "AppFrame"))) によって登録されます。 各フレームには、それぞれに関連付けられた一意のキーが必要です。 ほとんどのアプリでは、一般的に、1 つのフレームだけを使います。 2 つ目のフレームを宣言した場合は、それも登録する必要があります。 フレームを登録すると、そのフレームに対して 2 つの添付プロパティが設定されます。 1 つは、フレームに関連付けたキーです。もう 1 つは、フレームに関連付けられるセッション状態のディクショナリです。 前に登録されたフレームは、ナビゲーションと状態がすぐに復元されます。 フレームは登録を解除することもできます。解除すると、すべてのナビゲーション状態と履歴が破棄されます。

次に、重要な呼び出し SaveAsyncRestoreAsync について説明します。 SaveAsync は、SessionState 全体を保存するために使われます。 また、SuspensionManager.RegisterFrame を使って登録されたすべてのフレームには、現在のナビゲーション スタックが保持されます。それによって、アクティブ ページでデータを保存できるようになります。 その後、SessionState は、DataContractSerializer を使ってシリアル化され、ApplicationData によって定義されたローカル フォルダーに保存されているファイルに書き込まれます。

RestoreAsync は、前に保存された SessionState を読み取るために使われます。 また、RegisterFrame を使って登録されたすべてのフレームでは、前のナビゲーション状態が復元されます。それによって、アクティブ ページで状態を復元できるようになります。 SaveAsync と同じように、DataContractSerializer を使って、アプリのローカル フォルダー内のファイルに格納されている状態を逆シリアル化します。

アプリの状態を保存しようとしたときに発生する一般的なエラーが 2 つあります。

  • 個々のページで格納された型は、C# と VB の DataContractSerializer でシリアル化できる必要があります。 そのためには、任意のカスタム型を保存または復元する前に登録する必要があります。 SuspensionManager には、型をコレクションとして DataContractSerializer に渡す KnownTypes コレクションがあります。 SuspensionManager は、App.xaml のコード ビハインドの OnLaunched オーバーライドで状態を復元するために呼び出されるため、型はアプリ コンストラクターで登録することをお勧めします。

            public App()
            {
                this.InitializeComponent();
                this.Suspending += OnSuspending;
                SuspensionManager.KnownTypes.Add(typeof(MyCustomType));
            }
    
  • ナビゲーションを使って渡されたパラメーターは、プラットフォームでシリアル化できる必要があります。 ナビゲーション スタックの保存と復元を行う場合は、Frame.GetNavigationState()Frame.SetNavigationState() を呼び出します。 これらの呼び出しは、どちらも内部のシリアル化形式を使います。また、Frame.Navigate() のパラメーターとして渡されたすべての型は、プラットフォームでシリアル化できる必要があります。

SuspensionManager の使用は、NavigationHelper の実装でラップされます。

NavigationHelper は、次の重要な利便性を実現するページの実装です。

  • GoBack、GoForward、GoHome のイベント ハンドラー。
  • ナビゲーション用のマウスとキーボードのショートカット。
  • ナビゲーションの状態の管理とプロセス ライフタイム管理。

既定のビュー モデル

DefaultViewModel は、すべての複雑なページ項目テンプレートで使われています。 DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}" のように、DataContext はページ自体で定義されている DefaultViewModel にバインドされます。DefaultViewModel プロパティは、ObservableDictionary 型のプロパティであり、文字列 (キー) とオブジェクト (値) の対応関係を示したマップです。DefaultViewModel は、便宜的に提供されており、必要に応じて、厳密に型指定されたビュー モデルに変更できます。

各ページは、コード ビハインドで DefaultViewModel に対して設定されるプロパティにバインドされます。 例として、GroupedItemsPage を見てみましょう。 このページでは、CollectionViewSource の Source プロパティが Groups プロパティにバインドされています (Source="{Binding Groups}")。 Groups は、DefaultViewModel に格納されているキーと値のペアのキーです (this.DefaultViewModel["Groups"] = sampleDataGroups;)。

アプリのビュー状態と表示状態のマッピング

Windows 8 のテンプレートでは、LayoutAwarePage にビュー状態を処理するコードがありました。Windows 8.1 では、このコードが不要になっています。SplitPage ページと FileOpenPicker ページにのみ、ビュー状態を処理するコードが含まれています。どちらのページも、幅が 500px 以上のあらゆるウィンドウ サイズを処理するためのものです。

ナビゲーション

NavigationHelper には、GoBack と GoForward のコマンドが登録されます。 これらの実装では、ページに関連付けられている Frame があるかどうかをチェックし、ある場合は、Frame.GoBack() または Frame.GoForward() を呼び出す前に、そのフレームから戻ることや進むことができるかどうかをチェックします。これを上書きし、分割ページでの既定の動作を変更することができます。

また、NavigationHelper では、通常ナビゲーションに使われる一般的なマウスとキーボードのショートカットが登録されます。 戻る場合は、マウスの戻るボタン、"Alt + 左方向キー"、キーボードの前に戻るキーを使います。 進む場合は、マウスの進むボタン、"Alt + 右方向キー"、キーボードの進むキーを使います。

プロセス ライフタイム管理

NavigationHelper は、前に挙げた実装のほかにも、各ページに実装される OnNavigatedTo()OnNavigatedFrom() のイベント ハンドラーでも呼び出される必要があります。 このようなイベントが発生すると、NavigationHelper によってページごとの LoadState() と SaveState() の実装が呼び出されます。 これらの機能の実装は、ページごとにカスタマイズできます。それぞれ OnNavigatedTo()OnNavigatedFrom() の代わりに使います。

OnNavigatedFrom() は、ページが Frame に表示されるときに呼び出されます。 新しいページに移動するときに、そのページに関連付けられている状態を読み込みます。 ページを復元すると、そのページの前に保存した状態が復元されます。 その後、LoadState が呼び出され、各ページが反応できるようになります。 LoadState には、OnNavigatedTo に渡される元のナビゲーション パラメーターと、前のページの状態 (存在する場合) の 2 つのパラメーターがあります。

OnNavigatedFrom() は、ページが Frame に表示されなくなるときに呼び出されます。 ページから移動するときに、そのページの現在の状態を保存できます。 空のディクショナリが SaveState() に渡されます。 各ページでは、SaveState をオーバーライドし、キーを持つディクショナリ (文字列対オブジェクト) にオブジェクトを保存できます。 その後、このディクショナリは、そのページに関連付けられ、SuspensionManager によって追跡される特定のフレームの SessionState に追加されます。

  

  • 個々のページに格納されているデータは、DataContractSerializer でシリアル化できる必要があります。 詳しくは、このトピックの冒頭の SuspensionManager の説明をご覧ください。
  • また、ここで一時的な UI 情報だけを格納することも重要です。アプリが終了以外の手段によって閉じられると、この状態が失われます。

アプリの構造

アプリの構造を理解するために、グリッド アプリケーション プロジェクト テンプレートを使って作成したアプリを使います。 XAML を使用するすべての Windows ストア アプリは、App.xaml 内の Application オブジェクトとそれに関連するコード ビハインドが出発点となります。 アプリを作成した場合に最初に実行されるコードは、アプリ コンストラクターです。 これに続いて、さまざまなアクティブ化方法のいずれかが呼び出されます。この場合は、スタート画面のタイルからアプリを起動すると、OnLaunched イベントが呼び出されます。 この呼び出しでは、Frame が作成され、(前にアプリが終了した場合は) 前の状態が読み込まれます。その後、このフレームを使って、最初のページに移動します。 ページに移動すると、そのページの OnNavigatedTo イベント ハンドラーが NavigationHelper を呼び出します。NavigationHelper が実行されると、パラメーターが記録され、特定のページの前の状態情報が再読み込みされます。 次に、GroupedItemsPage でオーバーライドされた LoadState() メソッドが呼び出されます。 ここで、データが読み込まれ、既定のビュー モデルが設定されます。 別のページに移動すると、OnNavigatedFrom イベント ハンドラーによって NavigationHelper が呼び出され、それが SaveState() を呼び出してこのページの状態を保存します。SplitPage などの一時的な UI の状態を持つページで SaveState() がオーバーライドされ、新しいページに移動した後、LoadState() メソッドがもう一度呼び出されます。

関連トピック

Windows ストア アプリ用の C#、VB、C++ プロジェクト テンプレート

パート 2: アプリのライフサイクルと状態を管理する

パート 3: ナビゲーション、レイアウト、ビュー