UWPアプリにはシステム提供の[戻る]ボタンを表示できる。本稿では、このボタンを表示し、画面遷移を制御する方法を解説する。
powered by Insider.NET
PC用のWindows 10は、システムが[戻る]ボタンを表示するようになった。モバイル用のWindows 10には、Windows Phoneの時代から[戻る]ボタンがある。これらの[戻る]ボタンを、Windows 10のユニバーサルWindowsプラットフォーム用のアプリ(以降、UWPアプリ)ではどのように扱えばよいのだろうか? 本稿ではその方法を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #113」からダウンロードできる。
デスクトップ用とモバイル(=Windows 10を搭載したスマートフォン)用のUWPアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Community 2015を使っている。
*1 SLAT対応ハードウエアは、モバイルエミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能である。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウエアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 Windows 10モバイルエミュレーターを使用しないのであれば、32bit版でもよい。
*3 開発に使うWindows 10は「開発者モード」を有効にしておくこと(「設定アプリ」の[更新とセキュリティ]−[開発者向け]で、[開発者モード]ラジオボタンを選択)。そうしないと、VS 2015のXAMLエディターがエラーになる。また、本稿の内容が適用できるのは、Windowsのライフサイクル管理の上では「Windows 10, released in July 2015」と呼ばれるリリース、またはそれ以降。WinVerコマンドで表示されるバージョンは「10.0 (ビルド 10240)」。UWPアプリ開発におけるデバイスファミリーのバージョン指定としては「10.0.0.0」(Package.appxmanifestファイルのTargetDeviceFamily)である。なお、モバイルエミュレーターを使用しないのであれば、Home版でもよい。
*4 本稿に掲載したコードを試すだけなら、無償のExpressエディションやCommunityエディションで構わない。Visual Studio Express 2015 for Windows 10(製品版)はマイクロソフトのページから無償で入手できる(ページの左側で[Visual Studio 2015]−[Express 2015 for Windows 10]と選ぶ)。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、UWPアプリの開発には「for Windows 10」を使う(「for Desktop」はWPF/Windowsフォーム/Win32 APIのアプリ開発用)。また、Visual Studio Community 2015(製品版)もマイクロソフトのページから無償で入手できる。なお、英語版がインストールされた場合には、Microsoft Visual Studio 2015 Language Packの日本語版を追加インストールし、[オプション]ダイアログで言語を切り替える。
*5 使用しているVS 2015に含まれていない場合は、Windows SDK for Windows 10のページからダウンロードできる。本稿の内容が適用できるのは、作成したプロジェクトのプロパティに表示されるターゲットバージョンが「10.0; ビルド 10240」またはそれ以降。
モバイル用のWindows 10は、従来のWindows Phone 7.x/8.xを引き継いで、システムが[戻る]ボタンを提供していることはご存じだろう(次の画像)。
PC用のWindows 10でも、タブレットモードにするとタスクバーに[戻る]ボタンが表示される(次の画像)。
さらに、PC用のWindows 10では、タイトルバーに[戻る]ボタンが表示されているUWPアプリもある(次の画像)。これは、上の画像にあるタスクバー上の[戻る]ボタンと同じくシステムが表示しているボタンであり、タスクバー上の[戻る]ボタンとほぼ同じ動作をする。
なお、現在のWindows 10 IoT Coreでは、システムが[戻る]ボタンを提供していないことが分かっている(英語フォーラムのスレッド参照)。PCとモバイル以外のデバイスにも対応するUWPアプリの場合は、デバイスに応じてアプリ独自の[戻る]ボタンを表示する必要が出てくる。
UWPアプリのタイトルバーに[戻る]ボタンを表示するには、SystemNavigationManagerオブジェクト(Windows.UI.Core名前空間)のAppViewBackButtonVisibilityプロパティを設定すればよい。このプロパティはユニバーサルなので、デバイスによる切り分けは不要である。ただし、本稿執筆時点ではデスクトップ用Windows 10だけで有効だ(モバイルでは何も起きない)。
例えば、ページのOnNavigatedToメソッドのオーバーライドで、次のコードのように記述する。Windowsランタイムアプリは、「どのページを表示しているか」やページ間の遷移の履歴を、ページ内のFrameコントロール(Windows.UI.Xaml.Controls名前空間)で管理している。そこで、ページ内のFrameコントロールが前の画面に戻れる状態のとき(例えば、MainPage.xamlファイルで定義されている画面からAnotherPage.xamlファイルで定義されている画面に遷移をしたとき)は[戻る]ボタンを表示し、そうでないとき(例えば、アプリ実行直後にMainPage.xamlで定義されている画面が表示されたとき)は非表示にする。
Windows.UI.Core.SystemNavigationManager.GetForCurrentView()
.AppViewBackButtonVisibility
= Frame.CanGoBack
? Windows.UI.Core.AppViewBackButtonVisibility.Visible
: Windows.UI.Core.AppViewBackButtonVisibility.Collapsed;
Windows.UI.Core.SystemNavigationManager.GetForCurrentView() _
.AppViewBackButtonVisibility _
= If(Frame.CanGoBack,
Windows.UI.Core.AppViewBackButtonVisibility.Visible,
Windows.UI.Core.AppViewBackButtonVisibility.Collapsed)
システムの[戻る]ボタンがタップ/クリックされたときの処理は、SystemNavigationManagerオブジェクトのBackRequestedイベントで行えばよい。このイベントもユニバーサルであり、モバイル用Windows 10でも動作する。
例えば、次のコードのようにして、ページのOnNavigatedToメソッドのオーバーライドでイベントハンドラーを結び付け、イベントハンドラー内で前の画面に戻す処理を行う。
注意点が二つある。一つは、タスクバー上の[戻る]ボタンとモバイルの[戻る]ボタンは常に操作が可能なため、画面遷移履歴のない状態でも[戻る]ボタンが押せることだ。二つ目は、タスクバー上の[戻る]ボタンかモバイルの[戻る]ボタンが押されたときは、イベントハンドラーの引数eのHandledプロパティをtrueにセットする必要があることだ。trueにセットしないと、以前に表示していたアプリ(またはスタート画面)に戻ってしまう(これは、画面遷移履歴のない状態では正常な動作だ)。
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
……省略……
// システムの[戻る]ボタンに対応するイベントハンドラーを結び付ける
Windows.UI.Core.SystemNavigationManager.GetForCurrentView()
.BackRequested += MainPage_BackRequested;
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
……省略……
// システムの[戻る]ボタンに対応するイベントハンドラーを解除する
Windows.UI.Core.SystemNavigationManager.GetForCurrentView()
.BackRequested -= MainPage_BackRequested;
}
// システムの[戻る]ボタンが押された時のイベントハンドラー
private void MainPage_BackRequested(object sender,
Windows.UI.Core.BackRequestedEventArgs e)
{
if (Frame.CanGoBack)
{
Frame.GoBack();
e.Handled = true;
}
}
Protected Overrides Async Sub OnNavigatedTo(e As NavigationEventArgs)
MyBase.OnNavigatedTo(e)
……省略……
' システムの[戻る]ボタンに対応するイベントハンドラーを結び付ける
AddHandler _
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested,
AddressOf MainPage_BackRequested
End Sub
Protected Overrides Sub OnNavigatingFrom(e As NavigatingCancelEventArgs)
MyBase.OnNavigatingFrom(e)
……省略……
' システムの[戻る]ボタンに対応するイベントハンドラーを解除する
RemoveHandler _
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested,
AddressOf MainPage_BackRequested
End Sub
' システムの[戻る]ボタンが押された時のイベントハンドラー
Private Sub MainPage_BackRequested(sender As Object,
e As Windows.UI.Core.BackRequestedEventArgs)
If (Frame.CanGoBack) Then
Frame.GoBack()
e.Handled = True
End IfEnd Sub
さて、トップレベルのFrameコントロール内で画面遷移を行っている場合は、以上のようにそれぞれのページの中で[戻る]ボタンの処理を行えばよいのだが、メインページの中にナビゲーションメニューとそのコンテンツとしてFrameコントロールを置き、そのFrameコントロール内で画面を遷移させている場合はどうだろう? 「WinRT/Metro TIPS:ハンバーガーメニューで画面を遷移させるには?[Windows 10 UWPアプリ開発]」で紹介したような場合だ。
Frameコントロールは、外部からでもGoBackメソッドを呼び出してその内容だけを前のページに戻せる。つまり画面遷移については上記のようなコンテンツ構成でも問題なく実装できる。ただし、Frameコントロールの内容を前のページに戻したときに、ナビゲーションメニューの方でも同期を取ってアクティブになっている状態を変えなければならない(コンテンツとして配置したFrameコントロールにどのページが表示されているかがメニューに反映されるようにする)。ここが少々工夫の必要になるところだ。それには、FrameコントロールのNavigatedイベントを使うとよい。
例えば次の図のように、「MainPage」クラスに二つのイベントハンドラーを追加する。一つは前述したBackRequestedイベントのハンドラーだが、そこで呼び出すGoBackメソッドをコンテンツのFrameコントロールのものとする点が異なる。二つ目は、コンテンツのFrameコントロールのNavigatedイベントを受けるハンドラーだ。このハンドラーはFrameコントロール内での画面遷移が完了したときに呼び出されるので、ここでナビゲーションメニュー(図の中では「ハンバーガーメニュー」)の同期を取ればよい。具体的なコードは、別途公開のサンプルコードをご覧いただきたい。
実行している様子を次の画像に示す。
システムの[戻る]ボタンがタップ/クリックされたときの処理は、SystemNavigationManagerオブジェクトのBackRequestedイベントでユニバーサルに行える。ただし、デバイスによってはシステムが[戻る]ボタンを提供していないこともあるので注意が必要だ(本稿執筆時点ではIoT Coreにはないことが分かっている)。
なお、Frameコントロールには画面遷移が完了したときに発生するイベントがある。画面内にFrameコントロールを配置するときは思い出してほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.