次の方法で共有


2 ページ間のナビゲーションを実装する

フレームとページを使用して、アプリで基本的なピア ツー ピア ナビゲーションを有効にする方法について説明します。

ピア ツー ピア ナビゲーション

ほぼすべてのアプリでは、ページ間のナビゲーションが必要です。 1 つのコンテンツ ページを持つ単純なアプリでも、通常はナビゲーションを必要とする設定ページが存在します。 この記事では、XAML Page をアプリに追加し、 Frame を使用してページ間を移動する方法の基本について説明します。

重要

この例では、Microsoft Visual Studio の Blank App テンプレートを使用します。 Windows アプリ SDK/WinUI 3 アプリと UWP アプリのテンプレートには違いがあるため、アプリの種類に適したタブを選択してください。

1. 空のアプリを作成する

Visual Studio で空のアプリを作成するには:

  1. 開発コンピューターをセット アップするには、「Windows App SDK 用のツールをインストールする」を参照してください。
  2. Microsoft Visual Studio のスタート ウィンドウで、 新しいプロジェクトの作成または Visual Studio メニューの File>New>Project を選択します。
  3. 新しいプロジェクトの作成ダイアログのドロップダウン フィルターで、それぞれ C# または C++Windows、および WinUI を選択します。
  4. プロジェクト テンプレートとして [空のアプリ、パッケージ (WinUI 3 in Desktop)] を選択し、[次へ] をクリックします。 そのテンプレートで、WinUI 3 ベースのユーザー インターフェイスを使用したデスクトップ アプリが作成されます。
  5. [ プロジェクト名 ボックスに「 BasicNavigation」と入力し、[ Create をクリックします。
  6. プログラムを実行するには、メニューから Debug>Start Debugging を選択するか、F5 キーを押します。 開発用コンピューター上でソリューションをビルドして実行し、アプリがエラーなしで動作することを確認します。 空白のページが表示されます。
  7. デバッグを停止して Visual Studio に戻すには、アプリを終了するか、メニューから Stop Debugging をクリックします。
  8. テンプレートに含まれているコード例を MainWindow.xaml から削除し、分離コード ファイル MainWindow します。

ヒント

詳細については、「最初の WinUI 3 (Windows アプリ SDK) プロジェクトを作成するを参照してください。

2. フレームを使用してページ間を移動する

アプリに複数のページがある場合は、 Frame を使用してページ間を移動します。 Frame クラスは、NavigateGoBackGoForward、プロパティ (BackStackForwardStackBackStackDepth など) をサポート

Visual Studio で新しいWindows アプリ SDK プロジェクトを作成すると、プロジェクト テンプレートによってMainWindow クラス (Microsoft.UI.Xaml.Window 型) が作成されます。 ただし、 Frame または Page は作成せず、ナビゲーション コードも提供しません。

ページ間のナビゲーションを有効にするには、MainWindowのルート要素としてFrameを追加します。 これは、App.xaml分離コード ファイルの Application.OnLaunched メソッドのオーバーライドで行うことができます。 App分離コード ファイルを開き、OnLaunchedのオーバーライドを更新し、次に示すように NavigationFailed イベントを処理します。

// App.xaml.cs

protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    // Create a Frame to act as the navigation context and navigate to the first page
    Frame rootFrame = new Frame();
    rootFrame.NavigationFailed += OnNavigationFailed;
    // Navigate to the first page, configuring the new page
    // by passing required information as a navigation parameter
    rootFrame.Navigate(typeof(MainPage), args.Arguments);

    // Place the frame in the current Window
    m_window.Content = rootFrame;
    // Ensure the MainWindow is active
    m_window.Activate();
}

void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
    throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
// App.xaml.h

// Add after OnLaunched declaration.
void OnNavigationFailed(IInspectable const&, Microsoft::UI::Xaml::Navigation::NavigationFailedEventArgs const&);

///////////////
// App.xaml.cpp

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    window = make<MainWindow>();
    Frame rootFrame = Frame();
    rootFrame.NavigationFailed({ this, &App::OnNavigationFailed });
    rootFrame.Navigate(xaml_typename<BasicNavigation::MainPage>(), box_value(e.Arguments()));
    window.Content(rootFrame);
    window.Activate();
}

void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e)
{
    throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name);
}

Note

より複雑なナビゲーションを使用するアプリの場合は、通常、MainWindow のルートとして NavigationView を使用し、ナビゲーション ビューのコンテンツとして Frame を配置します。 詳細については、「 ナビゲーション ビューを参照してください。

Navigate メソッドは、このFrame内のコンテンツを表示するために使用されます。 ここでは、MainPage.xamlNavigate メソッドに渡されるため、メソッドはFrameMainPageを読み込みます。

アプリの初期ウィンドウへのナビゲーションが失敗すると、 NavigationFailed イベントが発生し、このコードはイベント ハンドラーで例外をスローします。

3. 基本ページを追加する

Blank App テンプレートでは、複数のアプリ ページは作成されません。 ページ間を移動する前に、いくつかのページをアプリに追加する必要があります。

アプリに新しい項目を追加するには:

  1. ソリューション エクスプローラーで、BasicNavigation プロジェクト ノードを右クリックしてコンテキスト メニューを開きます。
  2. コンテキスト メニューから Add>New Item を選択します。
  3. [ 新しい項目の追加 ] ダイアログ ボックスで、左側のウィンドウで WinUI ノードを選択し、中央のウィンドウで [ 空白ページ (WinUI 3) を選択します。
  4. [ ボックスに「 MainPage 」と入力し、 Add ボタンを押します。
  5. 手順 1 から 4. を繰り返して 2 番目のページを追加しますが、[ ボックスに「 Page2」と入力します。

これらのファイルは、 BasicNavigation プロジェクトの一部として一覧表示されます。

C# C++
  • MainPage.xaml
  • MainPage.xaml.cs
  • Page2.xaml
  • Page2.xaml.cs
  • MainPage.xaml
  • MainPage.xaml.cpp
  • MainPage.xaml.h
  • Page2.xaml
  • Page2.xaml.cpp
  • Page2.xaml.h

重要

C++ プロジェクトの場合別のページを参照する各ページのヘッダー ファイルに #include ディレクティブを追加する必要があります。 ここで示すページ間ナビゲーションの例では、mainpage.xaml.h ファイルに #include "Page2.xaml.h"が含まれています。さらに、page2.xaml.h には #include "MainPage.xaml.h"が含まれています。

C++ ページ テンプレートには、ページの XAML ファイルと分離コード ファイルから削除する必要がある Button およびクリック ハンドラー コードの例も含まれています。

ページにコンテンツを追加する

MainPage.xamlで、既存のページ コンテンツを次の内容に置き換えます。

<Grid>
    <TextBlock x:Name="pageTitle" Text="Main Page"
               Margin="16" Style="{StaticResource TitleTextBlockStyle}"/>
    <HyperlinkButton Content="Click to go to page 2"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</Grid>

この XAML では、次の内容が追加されます。

MainPage分離コード ファイルで、HyperlinkButton のClick イベントを処理する次のコードを追加します追加して、Page2.xamlへのナビゲーションを有効にします。

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2));
}
// pch.h
// Add this include in pch.h to support winrt::xaml_typename

#include <winrt/Windows.UI.Xaml.Interop.h>

////////////////////
// MainPage.xaml.h

void HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);

////////////////////
// MainPage.xaml.cpp

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::Page2>());
}

MainPage は、 Page クラスのサブクラスです。 Page クラスには、Pageを含むFrameを取得する読み取り専用の Frame プロパティがあります。 MainPage内のHyperlinkButtonClick イベント ハンドラーがFrame.Navigate(typeof(Page2))を呼び出すと、FramePage2.xamlの内容を表示します。

ページがフレームに読み込まれるたびに、そのページは PageStackEntry BackStack または FrameForwardStack に追加され、履歴と後方ナビゲーションが可能になります

ここで、 Page2.xamlで同じ操作を行います。 既存のページ コンテンツを次の内容に置き換えます。

<Grid>
    <TextBlock x:Name="pageTitle" Text="Page 2"
               Margin="16" Style="{StaticResource TitleTextBlockStyle}"/>
    <HyperlinkButton Content="Click to go to main page"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</Grid>

Page2分離コード ファイルで、HyperlinkButtonClick イベントを処理してMainPage.xamlに移動する次のコードを追加します。

// Page2.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(MainPage));
}
// Page2.xaml.h

void HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);

/////////////////
// Page2.xaml.cpp

void winrt::BasicNavigation::implementation::Page2::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::MainPage>());
}

アプリをビルドし、実行します。 [クリックしてページ 2 に移動] というリンクをクリックします。 上部に "Page 2" と表示されている 2 番目のページを読み込み、フレームに表示する必要があります。 次に、ページ 2 のリンクをクリックしてメイン ページに戻ります。

4. ページ間で情報を渡す

アプリは 2 つのページ間を移動するようになりましたが、まだ興味深い操作は行われません。 多くの場合、アプリに複数のページがある場合、ページは情報を共有する必要があります。 次に、最初のページから 2 番目のページにいくつかの情報を渡します。

MainPage.xamlで、前に追加したHyperlinkButtonを次のStackPanelに置き換えます。 これにより、テキスト文字列を入力するための TextBlock ラベルと TextBox name が追加されます。

<StackPanel VerticalAlignment="Center">
    <TextBlock HorizontalAlignment="Center" Text="Enter your name"/>
    <TextBox HorizontalAlignment="Center" Width="200" x:Name="name"/>
    <HyperlinkButton Content="Click to go to page 2"
                              Click="HyperlinkButton_Click"
                              HorizontalAlignment="Center"/>
</StackPanel>

次に、 Navigate メソッドの 2 番目のオーバーロードを使用し、テキスト ボックスから 2 番目のパラメーターとしてテキストを渡します。 この Navigate オーバーロードのシグネチャを次に示します。

public bool Navigate(System.Type sourcePageType, object parameter);
bool Navigate(TypeName const& sourcePageType, IInspectable const& parameter);

MainPage分離コード ファイルのHyperlinkButton_Click イベント ハンドラーで、name テキスト ボックスのText プロパティを参照する 2 つ目のパラメーターを Navigate メソッドに追加します。

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2), name.Text);
}
// MainPage.xaml.cpp

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{ 
    Frame().Navigate(xaml_typename<BasicNavigation::Page2>(), winrt::box_value(name().Text()));
}

Page2.xamlで、前に追加したHyperlinkButtonを次のStackPanelに置き換えます。 これにより、MainPageから渡されたテキスト文字列を表示するためのTextBlockが追加されます。

<StackPanel VerticalAlignment="Center">
    <TextBlock HorizontalAlignment="Center" x:Name="greeting"/>
    <HyperlinkButton Content="Click to go to page 1"
                     Click="HyperlinkButton_Click"
                     HorizontalAlignment="Center"/>
</StackPanel>

Page2分離コード ファイルで、次のコードを追加して、OnNavigatedTo メソッドをオーバーライドします。

// Page2.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.Parameter is string && !string.IsNullOrWhiteSpace((string)e.Parameter))
    {
        greeting.Text = $"Hello, {e.Parameter.ToString()}";
    }
    else
    {
        greeting.Text = "Hello!";
    }
    base.OnNavigatedTo(e);
}
// Page2.xaml.h

void Page2::OnNavigatedTo(Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e)
{
	auto propertyValue{ e.Parameter().as<Windows::Foundation::IPropertyValue>() };
	if (propertyValue.Type() == Windows::Foundation::PropertyType::String)
	{
		auto name{ winrt::unbox_value<winrt::hstring>(e.Parameter()) };
		if (!name.empty())
		{
			greeting().Text(L"Hello, " + name);
			__super::OnNavigatedTo(e);
			return;
		}
	}
	greeting().Text(L"Hello!");
	__super::OnNavigatedTo(e);
}

アプリを実行し、テキスト ボックスに自分の名前を入力し、 Click to go to page 2というリンクをクリックします。

MainPage内のHyperlinkButtonClick イベントがFrame.Navigate(typeof(Page2), name.Text)を呼び出すと、name.Text プロパティがPage2に渡され、ページに表示されるメッセージにイベント データの値が使用されます。

5. ページをキャッシュする

ページのコンテンツと状態は既定ではキャッシュされないため、情報をキャッシュする場合は、アプリの各ページで有効にする必要があります。

基本的なピア ツー ピアの例では、Page2の [Click to go to page 1] リンクをクリックすると、MainPageTextBox (およびその他のフィールド) が既定の状態に設定されます。 これを回避する方法の 1 つは、 NavigationCacheMode プロパティを使用して、フレームのページ キャッシュにページを追加するように指定することです。

既定では、ナビゲーションが発生するたびに、既定値を使用して新しいページ インスタンスが作成されます。 MainPage.xamlで、ページをキャッシュし、フレームのページ キャッシュを超えるまでページのすべてのコンテンツと状態の値を保持するには、NavigationCacheModeを (開始Page タグ内の) Enabledに設定します。 フレームキャッシュできるナビゲーション履歴のページ数を指定する CacheSize 制限を無視する場合はを Required に設定します。 ただし、デバイスのメモリ制限によっては、キャッシュ サイズの制限が重要になる可能性があることに注意してください。

<Page
    x:Class="BasicNavigation.MainPage"
    ...
    mc:Ignorable="d"
    NavigationCacheMode="Enabled">

メイン ページに戻ると、テキスト ボックスに入力した名前がまだ表示されます。

6. ページ切り替えアニメーションをカスタマイズする

既定では、ナビゲーションが発生すると、各ページがフレームにアニメーション化されます。 既定のアニメーションは、ウィンドウの下部からページを上にスライドさせる "開始" アニメーションです。 ただし、アプリのナビゲーションに適したさまざまなアニメーション オプションを選択できます。 たとえば、"ドリルイン" アニメーションを使用して、ユーザーがアプリに深く入り込んでいるような感覚を与えたり、水平スライド アニメーションを使用して 2 つのページがピアであるという感覚を与えたりすることができます。 詳細については、「 ページ切り替え」を参照してください。

これらのアニメーションは、 NavigationTransitionInfo のサブクラスによって表されます。 ページ切り替えに使用するアニメーションを指定するには、Navigate メソッドの 3 番目のオーバーロードを使用し、3 番目のパラメーター (infoOverride) としてNavigationTransitionInfoのサブクラスを渡します。 この Navigate オーバーロードのシグネチャを次に示します。

public bool Navigate(System.Type sourcePageType, 
                     object parameter,
                     NavigationTransitionInfo infoOverride);
bool Navigate(TypeName const& sourcePageType, 
              IInspectable const& parameter, 
              NavigationTransitionInfo const& infoOverride);

MainPage分離コード ファイルのHyperlinkButton_Click イベント ハンドラーで、infoOverride パラメーターを SlideNavigationTransitionInfo に設定する 3 番目のパラメーターを Navigate メソッドに追加Effect プロパティを FromRight に設定します。

// MainPage.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2), 
                   name.Text,
                   new SlideNavigationTransitionInfo() 
                       { Effect = SlideNavigationTransitionEffect.FromRight});
}
// pch.h

#include <winrt/Microsoft.UI.Xaml.Media.Animation.h>

////////////////////
// MainPage.xaml.cpp

using namespace winrt::Microsoft::UI::Xaml::Media::Animation;

// ...

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{   
    // Create the slide transition and set the transition effect to FromRight.
    SlideNavigationTransitionInfo slideEffect = SlideNavigationTransitionInfo();
    slideEffect.Effect(SlideNavigationTransitionEffect(SlideNavigationTransitionEffect::FromRight));
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::Page2>(),
        		     winrt::box_value(name().Text()),
                     slideEffect);
}

Page2分離コード ファイルのHyperlinkButton_Click イベント ハンドラーで、infoOverride パラメーターを SlideNavigationTransitionInfo Effect プロパティを FromLeft に設定します。

// Page2.xaml.cs

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(MainPage),
                   null,
                   new SlideNavigationTransitionInfo() 
                       { Effect = SlideNavigationTransitionEffect.FromLeft});
}
// Page2.xaml.cpp

using namespace winrt::Microsoft::UI::Xaml::Media::Animation;

// ...

void winrt::BasicNavigation::implementation::MainPage::HyperlinkButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{   
    // Create the slide transition and set the transition effect to FromLeft.
    SlideNavigationTransitionInfo slideEffect = SlideNavigationTransitionInfo();
    slideEffect.Effect(SlideNavigationTransitionEffect(SlideNavigationTransitionEffect::FromLeft));
    Frame().Navigate(winrt::xaml_typename<BasicNavigation::MainPage>(),
        		     nullptr,
                     slideEffect);
}

ページ間を移動すると、ページが左右にスライドします。これにより、この切り替えにより自然な感覚が得られ、ページ間の接続が強化されます。