UWP アプリのナビゲーション履歴と前に戻る移動Navigation history and backwards navigation for UWP apps

重要な API:BackRequested イベントSystemNavigationManager クラスOnNavigatedToImportant APIs: BackRequested event, SystemNavigationManager class, OnNavigatedTo

ユニバーサル Windows プラットフォーム (UWP) では、アプリのユーザーのナビゲーションの履歴内の移動や、デバイスによってはアプリ間の移動について、一貫性のある "戻る" ナビゲーション システムを提供します。The Universal Windows Platform (UWP) provides a consistent back navigation system for traversing the user's navigation history within an app and, depending on the device, from app to app.

アプリに前に戻る移動を実装するには、アプリの UI の左上隅に戻るボタンを配置します。To implement backwards navigation in your app, place a back button at the top left corner of your app's UI. アプリで NavigationView コントロールを使用する場合は、NavigationView の組み込みの戻るボタンを使用できます。If your app uses the NavigationView control, then you can use NavigationView's built-in back button.

ユーザーは、戻るボタンによって、アプリのナビゲーション履歴における前の場所に戻ることを想定しています。The user expects the back button to navigate to the previous location in the app's navigation history. ナビゲーション履歴に追加するナビゲーション操作の種類、および戻るボタンが押されたときの応答方法は、自由に決めることができます。Note that it's up to you to decide which navigation actions to add to the navigation history and how to respond to the back button press.

[戻る] ボタンBack button

戻るボタンを作成するには、NavigationBackButtonNormalStyle スタイルの Button コントロールを使用し、アプリの UI の左上隅にボタンを配置します (詳しくは、後の XAML コードの例をご覧ください)。To create a back button, use the Button control with the NavigationBackButtonNormalStyle style, and place the button at the top left hand corner of your app's UI (for details, see the XAML code examples below).

アプリの UI の左上隅にある [戻る] ボタン

<Page>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Button Style="{StaticResource NavigationBackButtonNormalStyle}"/>

    </Grid>
</Page>

アプリに上部 CommandBar がある場合、高さ 44px の Button コントロールは 48px の AppBarButtons とはぴったり合いません。If your app has a top CommandBar, the Button control that is 44px in height will not align with 48px AppBarButtons very nicely. 不整合を避けるために、Button コントロールの最上部を 48px の境界内部に合わせてください。However, to avoid inconsistency, align the top of the Button control inside the 48px bounds.

上部のコマンド バーの [戻る] ボタン

<Page>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <CommandBar>
            <CommandBar.Content>
                <Button Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top"/>
            </CommandBar.Content>
        
            <AppBarButton Icon="Delete" Label="Delete"/>
            <AppBarButton Icon="Save" Label="Save"/>
        </CommandBar>
    </Grid>
</Page>

アプリ内で動き回る UI 要素を最小化するために、バックスタックに何もないときに、無効になった戻るボタンを表示します (以下のコード例を参照)。In order to minimize UI elements moving around in your app, show a disabled back button when there is nothing in the backstack (see code example below). ただし、アプリにバックスタックがないことが予想される場合は、戻るボタンを表示する必要はありません。However, if you expect your app will never have a backstack, you don’t need to display the back button at all.

[戻る] ボタンの状態

コードの例Code example

次のコード例は、戻るボタンで前に戻る移動の動作を実装する方法を示しています。The following code example demonstrates how to implement backwards navigation behavior with a back button. このコードでは、Button の Click イベントに応答し、新しいページに移動したときに呼び出される OnNavigatedTo でボタンの表示を無効/有効にします。The code responds to the Button Click event and disables/enables the button visibility in OnNavigatedTo, which is called when navigating to a new page. このコード例では、BackRequested イベントのリスナーを登録することで、ハードウェアおよびソフトウェア システムの戻るキーからの入力も処理しています。The code example also handles inputs from hardware and software system back keys by registering a listener for the BackRequested event.

<!-- MainPage.xaml -->
<Page x:Class="AppName.MainPage">
...
<Button x:Name="BackButton" Click="Back_Click" Style="{StaticResource NavigationBackButtonNormalStyle}"/>
...
<Page/>

分離コード:Code-behind:

// MainPage.xaml.cs
public MainPage()
{
    KeyboardAccelerator GoBack = new KeyboardAccelerator();
    GoBack.Key = VirtualKey.GoBack;
    GoBack.Invoked += BackInvoked;
    KeyboardAccelerator AltLeft = new KeyboardAccelerator();
    AltLeft.Key = VirtualKey.Left;
    AltLeft.Invoked += BackInvoked;
    this.KeyboardAccelerators.Add(GoBack);
    this.KeyboardAccelerators.Add(AltLeft);
    // ALT routes here
    AltLeft.Modifiers = VirtualKeyModifiers.Menu;
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    BackButton.IsEnabled = this.Frame.CanGoBack;
}

private void Back_Click(object sender, RoutedEventArgs e)
{
    On_BackRequested();
}

// Handles system-level BackRequested events and page-level back button Click events
private bool On_BackRequested()
{
    if (this.Frame.CanGoBack)
    {
        this.Frame.GoBack();
        return true;
    }
    return false;
}

private void BackInvoked (KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
    On_BackRequested();
    args.Handled = true;
}
// MainPage.cpp
#include "pch.h"
#include "MainPage.h"

#include "winrt/Windows.System.h"
#include "winrt/Windows.UI.Xaml.Controls.h"
#include "winrt/Windows.UI.Xaml.Input.h"
#include "winrt/Windows.UI.Xaml.Navigation.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;

namespace winrt::PageNavTest::implementation
{
    MainPage::MainPage()
    {
        InitializeComponent();

        Windows::UI::Xaml::Input::KeyboardAccelerator goBack;
        goBack.Key(Windows::System::VirtualKey::GoBack);
        goBack.Invoked({ this, &MainPage::BackInvoked });
        Windows::UI::Xaml::Input::KeyboardAccelerator altLeft;
        altLeft.Key(Windows::System::VirtualKey::Left);
        altLeft.Invoked({ this, &MainPage::BackInvoked });
        KeyboardAccelerators().Append(goBack);
        KeyboardAccelerators().Append(altLeft);
        // ALT routes here.
        altLeft.Modifiers(Windows::System::VirtualKeyModifiers::Menu);
    }

    void MainPage::OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e)
    {
        BackButton().IsEnabled(Frame().CanGoBack());
    }

    void MainPage::Back_Click(IInspectable const&, RoutedEventArgs const&)
    {
        On_BackRequested();
    }

    // Handles system-level BackRequested events and page-level back button Click events.
    bool MainPage::On_BackRequested()
    {
        if (Frame().CanGoBack())
        {
            Frame().GoBack();
            return true;
        }
        return false;
    }

    void MainPage::BackInvoked(Windows::UI::Xaml::Input::KeyboardAccelerator const& sender,
        Windows::UI::Xaml::Input::KeyboardAcceleratorInvokedEventArgs const& args)
    {
        args.Handled(On_BackRequested());
    }
}

上の例では、単一ページに対する戻る移動を処理しています。Above, we handle backwards navigation for a single page. 戻る移動から特定のページを除外する場合や、ページを表示する前にページ レベルのコードを実行する場合は、各ページで移動を処理できます。You can handle navigation in each page if you want to exclude specific pages from back navigation, or you want to execute page-level code before displaying the page.

アプリ全体について戻る移動を処理するには、App.xaml 分離コード ファイル内で BackRequested イベントに対するグローバル リスナーを登録します。To handle backwards navigation for an entire app, you'll register a global listener for the BackRequested event in the App.xaml code-behind file.

App.xaml 分離コード:App.xaml code-behind:

// App.xaml.cs
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += App_BackRequested;
Frame rootFrame = Window.Current.Content;
rootFrame.PointerPressed += On_PointerPressed;

private void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
    e.Handled = On_BackRequested();
}

private void On_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    bool isXButton1Pressed =
        e.GetCurrentPoint(sender as UIElement).Properties.PointerUpdateKind == PointerUpdateKind.XButton1Pressed;

    if (isXButton1Pressed)
    {
        e.Handled = On_BackRequested();
    }
}

private bool On_BackRequested()
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame.CanGoBack)
    {
        rootFrame.GoBack();
        return true;
    }
    return false;
}
// App.cpp
#include <winrt/Windows.UI.Core.h>
#include "winrt/Windows.UI.Input.h"
#include "winrt/Windows.UI.Xaml.Input.h"

#include "App.h"
#include "MainPage.h"

using namespace winrt;
...

    Windows::UI::Core::SystemNavigationManager::GetForCurrentView().BackRequested({ this, &App::App_BackRequested });
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }
    rootFrame.PointerPressed({ this, &App::On_PointerPressed });
...

void App::App_BackRequested(IInspectable const& /* sender */, Windows::UI::Core::BackRequestedEventArgs const& e)
{
    e.Handled(On_BackRequested());
}

void App::On_PointerPressed(IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e)
{
    bool isXButton1Pressed =
        e.GetCurrentPoint(sender.as<UIElement>()).Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::XButton1Pressed;

    if (isXButton1Pressed)
    {
        e.Handled(On_BackRequested());
    }
}

// Handles system-level BackRequested events.
bool App::On_BackRequested()
{
    if (Frame().CanGoBack())
    {
        Frame().GoBack();
        return true;
    }
    return false;
}

さまざまなデバイスとフォーム ファクター向けに最適化Optimizing for different device and form factors

この前に戻る移動の設計ガイダンスはすべてのデバイスに適用可能ですが、最適化によってさまざまなデバイスとフォーム ファクターに適したものになります。This backwards navigation design guidance is applicable to all devices, but different device and form factors may benefit from optimization. これは、さまざまなシェルでサポートされているハードウェアの戻るボタンによっても変わります。This also depends on the hardware back button supported by different shells.

  • 電話/タブレット: ハードウェアまたはソフトウェアの戻るボタンは、携帯電話やタブレットに常に存在しますが、わかりやすくするために、アプリ内の戻るボタンを描画することをお勧めします。Phone/Tablet: A hardware or software back button is always present on mobile and tablet, but we recommend drawing an in-app back button for clarity.
  • デスクトップ/ハブ: アプリの UI の左上隅にアプリ内の戻るボタンを描画します。Desktop/Hub: Draw the in-app back button on the top left corner of your app's UI.
  • Xbox/テレビ: 不要な UI 要素が追加されるため、戻るボタンは描画しません。Xbox/TV: Do not draw a back button, for it will add unnecessary UI clutter. 代わりに、ゲームパッドの B ボタンで前に戻ります。Instead, rely on the Gamepad B button to navigate backwards.

アプリが複数のデバイスで実行される場合は、Xbox 用の視覚的なカスタム トリガーを作成してボタンの表示/非表示を切り替えます。If your app will run on multiple devices, create a custom visual trigger for Xbox to toggle the visibility of button. NavigationView コントロールでは、Xbox でアプリが実行されている場合に、戻るボタンの表示/非表示が自動的に切り替わります。The NavigationView control will automatically toggle the back button's visibility if your app is running on Xbox.

"戻る" ナビゲーションの場合に、次の入力をサポートすることをお勧めします。We recommend supporting the following inputs for back navigation. (これらの入力の一部はシステム BackRequested でサポートされていないため、別のイベントで処理する必要があります)。(Note that some of these inputs are not supported by the system BackRequested and must be handled by separate events.)

入力Input イベントEvent
Windows の BackSpace キーWindows-Backspace key BackRequestedBackRequested
ハードウェアの戻るボタンHardware back button BackRequestedBackRequested
シェル タブレット モードの戻るボタンShell tablet mode back button BackRequestedBackRequested
VirtualKey.XButton1VirtualKey.XButton1 PointerPressedPointerPressed
VirtualKey.GoBackVirtualKey.GoBack KeyboardAccelerator.BackInvokedKeyboardAccelerator.BackInvoked
Alt + 左方向キーAlt+LeftArrow key KeyboardAccelerator.BackInvokedKeyboardAccelerator.BackInvoked

上のコード例は、これらすべての入力を処理する方法を示してます。The code examples provided above demonstrate how to handle all of these inputs.

下位互換性のためのシステムの戻る動作System back behavior for backward compatibilities

以前、UWP アプリは前に戻る移動のために AppViewBackButtonVisibility を使用しました。Previously, UWP apps used AppViewBackButtonVisibility for backwards navigation. その API は下位互換性を確保するため引き続きサポートされますが、AppViewBackButtonVisibility に依存することはもうお勧めできません。The API will continue to be supported to ensure backward compatibility, but we no longer recommend relying on AppViewBackButtonVisibility. 代わりに、アプリで独自のアプリ内の戻るボタンを描画してください。Instead, your app should draw its own in-app back button.

アプリで AppViewBackButtonVisibility の使用を続けた場合、システム UI では、タイトル バーの内部に戻るボタンがレンダリングされます。If your app continues using AppViewBackButtonVisibility, then the system UI will render the system back button inside the title bar. (戻るボタンの外観とユーザー操作は以前のビルドと変わりありません。)(The appearance and user interactions for the back button are unchanged from previous builds.)

タイトル バーの戻るボタン

カスタムの "戻る" ナビゲーションの動作のガイドラインGuidelines for custom back navigation behavior

独自のバック スタック ナビゲーションを提供する場合、エクスペリエンスが他のアプリと一貫している必要があります。If you choose to provide your own back stack navigation, the experience should be consistent with other apps. ナビゲーション操作では、次のパターンに従うことをお勧めします。We recommend that you follow the following patterns for navigation actions:

ナビゲーション操作Navigation action ナビゲーション履歴への追加Add to navigation history?
ページ間、異なるピア グループPage to page, different peer groups はい Yes

この図では、ユーザーはピア グループを横断して、アプリのレベル 1 からレベル 2 に移動します。そのため、このナビゲーションはナビゲーション履歴に追加されます。In this illustration, the user navigates from level 1 of the app to level 2, crossing peer groups, so the navigation is added to the navigation history.

Navigation across peer groups

次の図では、ユーザーは同じレベルにある 2 つのピア グループの間を移動し、この場合もピア グループを横断します。そのため、このナビゲーションはナビゲーション履歴に追加されます。In the next illustration, the user navigates between two peer groups at the same level, again crossing peer groups, so the navigation is added to the navigation history.

Navigation across peer groups

ページ間、同じピア グループ、ナビゲーション要素は画面上に表示されない Page to page, same peer group, no on-screen navigation element

ユーザーは、同じピア グループでページ間を移動します。The user navigates from one page to another with the same peer group. 両方のページに直接的なナビゲーションを提供する画面上のナビゲーション要素 (NavigationView など) はありません。There is no on-screen navigation element (such as NavigationView) that provides direct navigation to both pages.

はい Yes

次の図では、ユーザーは同じピア グループ内の 2 つのページ間を移動し、ナビゲーションはナビゲーション履歴に追加する必要があります。In the following illustration, the user navigates between two pages in the same peer group, and the navigation should be added to the navigation history.

Navigation within a peer group

ページ間、同じピア グループ、画面上に表示されるナビゲーション要素を使う Page to page, same peer group, with an on-screen navigation element

ユーザーは、同じピア グループ内のページ間を移動します。The user navigates from one page to another in the same peer group. 両方のページは同じナビゲーション要素に表示されます (NavigationView など)。Both pages are shown in the same navigation element, such as NavigationView.

場合によって異なります It depends

はい、ナビゲーション履歴に追加しますが、2 つの注目すべき例外があります。Yes, add to the navigation history, with two notable exceptions. アプリのユーザーがピア グループ内でページ間を頻繁に切り替えることが予想される場合、またはナビゲーション階層を保持する場合は、ナビゲーション履歴に追加しないでください。If you expect users of your app to switch between pages in the peer group frequently, or if you wish to preserve the navigational hierarchy, then do not add to the navigation history. この場合、ユーザーが戻るボタンを押すと、現在のピア グループに移動する前に表示していた最後のページに戻ります。In this case, when the user presses back, go back to the last page before the user navigated to the current peer group.

Navigation across peer groups when a navigation element is present

一時的な UI の表示 Show a transient UI

アプリは、ダイアログ、スプラッシュ画面、スクリーン キーボードなどのポップアップ ウィンドウや子ウィンドウを表示します。または、アプリが複数選択モードなどの特別なモードに移行します。The app displays a pop-up or child window, such as a dialog, splash screen, or on-screen keyboard, or the app enters a special mode, such as multiple selection mode.

いいえ No

ユーザーが戻るボタンを押すと、一時的な UI が閉じられ (スクリーン キーボードが非表示になる、ダイアログがキャンセルされるなど)、一時的な UI を生成したページに戻ります。When the user presses the back button, dismiss the transient UI (hide the on-screen keyboard, cancel the dialog, etc) and return to the page that spawned the transient UI.

Showing a transient UI

項目の列挙 Enumerate items

アプリが、マスター/詳細リストで選んだ項目の詳細など、画面上の項目のコンテンツを表示します。The app displays content for an on-screen item, such as the details for the selected item in master/details list.

いいえ No

項目の列挙は、ピア グループ内の移動に似ています。Enumerating items is similar to navigating within a peer group. ユーザーが戻るボタンを押すと、項目の列挙が表示されている現在のページの前のページに移動されます。When the user presses back, navigate to the page that preceded the current page that has the item enumeration.

Iterm enumeration

ResumingResuming

ユーザーが別のアプリに切り替えた後で、元のアプリに戻った場合は、ナビゲーション履歴にある最後のページに戻すことをお勧めします。When the user switches to another app and returns to your app, we recommend returning to the last page in the navigation history.