起動時に以前の画面を復元するには?[Win 8]WinRT/Metro TIPS

Windowsストア・アプリには、「終了した後で再実行されるときに、ページの状態を復元しろ」というルールがある。とても面倒そうだが、どうすればよいのだろうか。

» 2012年09月20日 00時00分 公開
[山本康彦BluewaterSoft]
WinRT/Metro TIPS
業務アプリInsider

powered by Insider.NET

「WinRT/Metro TIPS」のインデックス

連載目次はこちら

 前回のTIPSでは、Windowsストア・アプリ(旧称: Metroスタイル・アプリ)で表示したページの状態を維持するために、ページのインスタンスを保持しておく方法を説明した。しかしさらに、「終了した後で再び実行されるときも、ページの状態を復元しろ」というルールがある。とても面倒そうだが、どうすればよいのだろうか?

 そこで本稿では、アプリの起動時に以前のページの状態を復元する方法を説明する。

事前準備

 Windows 8(以降、Win 8)向けのWindowsストア・アプリを開発するには、Win 8とVisual Studio 2012(以降、VS 2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。本稿ではWin 8とVS 2012 Expressを使用している。

リジュームの課題

 Windowsストア・アプリのライフサイクルは、次の図のように説明される。

Windowsストア・アプリのライフサイクル

 詳細は特集記事「Metroスタイル・アプリの開発者が知るべき3つのこと」を参照してほしいが、一度終了した後で次に起動(=アクティブ化)されるときは、ユーザーには中断状態からの再開(=リジューム)と同じに見せかけなければならない。

 リジューム時には、次に示すような事項を復元する必要があるだろう。

  • 表示していたページのインスタンス
  • そのページまでのナビゲーション履歴
  • 表示していたデータ
  • 入力中のデータや選択項目

表示していたページとナビゲーション履歴をリジュームするには?

 幸いなことに、[グリッド アプリケーション(XAML)」や[分割アプリケーション(XAML)]などのプロジェクト・テンプレートにより(ひな型コードとして)自動生成されたSuspensionManagerクラスが、表示していたページとそこまでのナビゲーション履歴の保存と復元をサポートしている。

 また、正常に終了されなかった場合は、リジュームせずに初期状態でアクティブ化しなければならないのだが、その切り分けも自動生成されたAppクラスがサポートしている。

表示データをリジュームするには?

 画面に表示していたデータは、少なければローカルに保存しておいてもよいが、多い場合はリジューム時に再取得した方がよいだろう。その場合は、再取得するために必要なパラメータだけを保存しておく。データを保存・復元する方法は次項の入力データと同様である。

入力データを保存するには?

 入力中の文字列を保存・復元するコードを実装してみよう。新しく[グリッド アプリケーション (XAML)]プロジェクトを作り、適当にテキストボックスを配置する(名前は「userInputTextbox」とする)。

 そのページのSaveStateメソッドに次のコードを記述する。なお、このメソッドは、自動生成されたLayoutAwarePageクラスのメソッドをオーバーライドしている。そのページにSaveStateメソッドが存在しないときは、「override」と打ってIntelliSenseを出し、その一覧から「SaveState」メソッドを選択すれば、メソッドのスケルトンが自動生成される。

protected override void SaveState(Dictionary<string, object> pageState)
{
  base.SaveState(pageState);
  pageState["userInputText"] = userInputTextbox.Text;
}


Protected Overrides Sub SaveState(pageState As Dictionary(Of String, Object))
  MyBase.SaveState(pageState)
  pageState("userInputText") = userInputTextbox.Text
End Sub


テキストボックスの文字列を保存するコード(上:C#、下:VB)
[グリッド アプリケーション (XAML)]プロジェクト・テンプレートで自動生成されたGroupedItemsPage.xaml.cs/.vbファイルにメソッドを追加した例。


 なお、データは「_sessionState.xml」(=SuspensionManagerクラスのsessionStateFilename定数として定義されている)という名前のファイルに保存される。保存されるフォルダは、Win 8がインストールされているドライブの「\Users\{ユーザー名}\AppData\Local\Packages\{パッケージ・ファミリ名}\LocalState」になる。ここで、{パッケージ・ファミリ名}は、アプリケーション・マニフェスト・ファイル(=[ソリューション エクスプローラー]上から[Package.appxmanifest]ファイル項目を開き、[パッケージ化]タブの[パッケージ ファミリ名]欄)に記述されている一意の識別名である(この値を変更するには、[パッケージ化]タブの[パッケージ名]欄を設定し直せばよい)。

中断時の処理をテストするには?

 さっそく先ほどのコードを試してみよう。デバッグ時には、以下のようにしてVS 2012で中断をシミュレートする。

 まず、そのための[デバッグの場所]ツールバーを表示させる。メニューバーから表示させるには、[表示]−[ツール バー]−[デバッグの場所]を実行する。あるいは、次の画像の説明のようにしてもよい。

[デバッグの場所]ツールバーを表示させる
VS 2012で中断をシミュレートするためのツールバーを表示させようとしてるところ。
  (1)メニューバーかツールバーの適当な場所で右クリックすると、コンテキスト・メニューが出てくる(赤枠内)。
  (2)コンテキスト・メニューから[デバッグの場所]を選ぶ。

 [デバッグの場所]ツールバーには、次の画像のように[中断]というコマンドがあり、デバッグ中に中断や再開などをシミュレートできる。

[デバッグの場所]ツール・バー
[中断]というコマンドがある。選択肢は3つ(赤枠内)。

 それでは実際にデバッグ実行して、次の画像のようにテキストボックスに何か入力したところで、中断してみてほしい。

実行結果1(エミュレータ)
テキストボックスに文字列を入力しているところ。このまま中断状態にする。

 これで前述の_sessionState.xmlファイルが作成されたはずだ。メモ帳などで内容を確認できる。

実行結果2(_sessionState.xmlファイルの内容)
入力中だった文字列が保存されている(赤枠内)。

 なお、SaveStateメソッドはページが移動するときにも呼び出される(実際に保存されるのは中断時)。

入力データを復元するには?

 先ほどのコードで保存した文字列を復元するには、そのページのLoadStateメソッドに次のようにコードを追加する。

protected override void LoadState(Object navigationParameter,
                                  Dictionary<String, Object> pageState)
{
  var sampleDataGroups
    = SampleDataSource.GetGroups((String)navigationParameter);
  this.DefaultViewModel["Groups"] = sampleDataGroups;

  // ↓テキストボックスに入力されていた文字列を復元する
  if (pageState != null)
    userInputTextbox.Text = pageState["userInputText"].ToString();
}


Protected Overrides Sub LoadState(navigationParameter As Object, _
                                  pageState As Dictionary(Of String, Object))
  Dim sampleDataGroups As IEnumerable(Of Data.SampleDataGroup) _
    = Data.SampleDataSource.GetGroups(DirectCast(navigationParameter, String))
  Me.DefaultViewModel("Groups") = sampleDataGroups

  ' ↓テキストボックスに入力されていた文字列を復元する
  If pageState IsNot Nothing Then
    userInputTextbox.Text = pageState("userInputText").ToString()
  End If
End Sub


テキストボックスの文字列を復元するコード(上:C#、下:VB)
[グリッド アプリケーション (XAML)]プロジェクト・テンプレートで自動生成されたGroupedItemsPage.xaml.cs/.vbファイルに記述した例。


 これで、入力中に中断してから終了させ、その後に再び実行すると、文字列が復元されて表示されるはずである。

 なお、LoadStateメソッドはページのインスタンスが作られたときに呼び出される。そのため、入力中にほかのページへ移動してから再び戻って来たときにも文字列が復元される。前回のTIPSではページのインスタンスを保持したが、このようにしてもページの状態を復元できるのである。

まとめ

 起動時に以前の画面を復元するには、ページごとにSaveStateメソッドとLoadStateメソッドでデータの保存・復元処理を行えばよい。

 アプリのライフサイクルの設計や実装については、次のURLが参考になる。

 なお、本稿では説明しなかったが、「強制終了されても失ってはいけないアプリ・データの場合には、ApplicationDataクラス(Windows.Storage名前空間)のRoamingSettingsプロパティLocalSettingsプロパティに保存する」ということも覚えておいてほしい。

「WinRT/Metro TIPS」のインデックス

WinRT/Metro TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。