セカンダリタイルをタップされたときの動作を追加する
セカンダリタイルがタップされると、「App.xaml.cs」ファイルのOnLaunchedメソッドが必ず呼び出される。そのとき、セカンダリタイルを作るときにセットしたArgmentsが、OnLaunchedメソッドの引数に入って来るので、セカンダリタイルに応じた処理を実行できる。
今回は、Argmentsにセットされている画面に遷移させる。その処理は、通常起動時の画面遷移が終わった時点で行えばよい(次のコード)。
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
……省略……
{
// ナビゲーション スタックが復元されていない場合、最初のページに移動します。
if (!rootFrame.Navigate(typeof(HubPage)))
{
throw new Exception("Failed to create initial page");
}
}
//【第9回】セカンダリタイルをタップされたときの対応
if (! string.IsNullOrEmpty(e.Arguments))
{
string[] args = e.Arguments.Split(','); // 文字列をカンマで区切る
// 2番目のカラムには、URLエンコードされたフィードのタイトルが入っているので、復元する
var feedTitle = System.Net.WebUtility.UrlDecode(args[1]);
// フィードのタイトルを引数として、記事一覧画面に遷移(第6回参照)
rootFrame.Navigate(typeof(FeedPage), feedTitle);
}
// 現在のウィンドウがアクティブであることを確認します
Window.Current.Activate();
}
通常の画面遷移の後で目的の画面に遷移させているのは、[戻る]ボタンでメイン画面に戻れるようにするためだ。通常の画面遷移を飛ばして目的の画面に直接遷移させてしまうと、メイン画面が表示できなくなってしまう。
なお、これまではセカンダリタイルからの起動を考えていなかったため、AppクラスのOnLauncedメソッドは1回しか実行されないと仮定していた。実行中でもセカンダリタイルをタップされるとOnLauncedメソッドが呼び出されるので、次に示す改修が必要になる。
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
……省略……
//【第6回】正式なロジックの呼び出しに置き換える
//var feedsData = App.Current.Resources["feedsDataSource"] as DataModel.FeedsData;
//Logic.DataLoader.LoadStart(feedsData);
//【第9回】実行中にセカンダリタイルをタップされたときの対応として、下のif文内に移動した
//【第8回】ローミング・データが同期されたときの処理に必要
//_dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
//【第9回】実行中にセカンダリタイルをタップされたときの対応として、下のif文内に移動した
Frame rootFrame = Window.Current.Content as Frame;
// ウィンドウにすでにコンテンツが表示されている場合は、アプリケーションの初期化を繰り返さずに、
// ウィンドウがアクティブであることだけを確認してください
if (rootFrame == null)
{
//【第9回】データのロードが完了したときのイベントハンドラーを登録する
Logic.DataLoader.LoadCompleted += this.OnLoadDataCompleted;
//【第9回】実行中にセカンダリタイルをタップされたときの対応として、ここに移動させた
{
//【第6回】正式なロジックの呼び出しに置き換える
var feedsData = App.Current.Resources["feedsDataSource"] as DataModel.FeedsData;
Logic.DataLoader.LoadStart(feedsData);
//【第8回】ローミング・データが同期されたときの処理に必要
_dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
}
// ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
rootFrame = new Frame();
……省略……
セカンダリタイルの登録/解除は、一通り動作の確認ができれば大丈夫だろう。TileIdが規定の文字数(64文字)を超えていると例外が出る。今回はセカンダリタイルを登録する記事一覧画面は3つしかないのでTileIdが衝突する心配はなかった*6。
セカンダリタイルをタップしたときの動作の検証はちょっと厄介だ。次の表に示すパターンでセカンダリタイルをタップして動作を確かめる。
タップ前の状態 | タップされたときの動作 |
---|---|
アプリが起動していない (中断状態や、中断からシャットダウンされた状態でもない) |
メイン画面経由で、セカンダリタイルから呼び出される画面に遷移 |
アプリが起動していて、 セカンダリタイルから呼び出される画面になっている |
何もしない |
アプリが起動していて、 セカンダリタイルから呼び出される画面になっていない |
セカンダリタイルから呼び出される画面に遷移 |
セカンダリタイルから呼び出される画面のときに、中断→シャットダウンされた後 | 画面遷移履歴が復元され、セカンダリタイルから呼び出される画面が表示される(二重に遷移してはいけない) |
セカンダリタイルから呼び出される画面になっていないときに、中断→シャットダウンされた後 | 画面遷移履歴が復元され、さらにセカンダリタイルから呼び出される画面に遷移 |
セカンダリタイルをタップするときの動作パターン |
この動作の話はスペックを考えるときに見落としていたため、実装されていない。そのため、セカンダリタイルから呼び出されるべき画面への画面遷移が常に発生してしまう。セカンダリタイルをタップ→スタート画面に戻る→セカンダリタイルをタップ→スタート画面に戻る……と繰り返し操作すると、見た目は同じ画面だが何回も画面遷移してしまっていて、[戻る]ボタンをタップすると同じ画面が続くことになる。
この問題の対処は読者の皆さんへの宿題としよう。別途公開しているサンプルコードには回答となる実装もしてあるので、参考にしていただきたい。
*6記事表示画面のピン留めを実装するときには、記事のタイトルが衝突する可能性が出てくる。TileIdには記事タイトルをURLエンコードした文字列の先頭64文字(日本語だけなら10文字分相当)しか使えないので、バッティングする可能性は大きいだろう。そこでハッシュ値を埋め込むなどして、ユニークなTileIdを生成する工夫が必要になる。
デバッグ実行中に記事表示画面で「Just-In-Timeデバッガー」のエラーが出ることがある。このエラーが発生すると、デスクトップ画面に切り替わり、「Visual Studio Just-In-Timeデバッガー」というタイトルのダイアログが表示される(次の画像)。
このエラーは、WebViewコントロールがダウンロードしてきたWebページのコンテンツに含まれているJavaScriptを実行しているときに発生したものだ。ダウンロードしたJavaScriptで起きているエラーであり、作成したプログラムの不具合ではないので、安心してデバッグ実行を継続してよい。また、Visual Studioからデバッグ実行するのではなく、スタート画面のタイルから起動したときには、このダイアログは出ない。
このエラーが頻繁に出るようなら、動作確認のときには、[デバッグ実行]ではなく[デバッグなしで開始](=メニューバーの[デバッグ]−[デバッグなしで開始])を使うとよいだろう。このエラーへの対処法について詳しくは、次の記事の「Just-In-Timeデバッガのエラー・ダイアログについて」の項を参照してほしい。
今回は、アプリの魅力を高めるために効果的な情報を提示する手段を学び、ライブタイルとセカンダリタイルを実装した。バックグラウンドタスクの実装は入門の範囲を超えてしまうので説明しなかったが、ライブタイルやバッジを随時更新する手段として有効なので、慣れてきたらぜひ挑戦してもらいたい。
次回は「検索ボックスを付ける」。読み込んだRSSフィードの記事タイトルを検索できるようにして、さらにアプリの価値を高めよう。
Copyright© Digital Advantage Corp. All Rights Reserved.