2 ページ間のナビゲーションを実装する
フレームとページを使用して、アプリで基本的なピア ツー ピア ナビゲーションを有効にする方法について説明します。
ほぼすべてのアプリでは、ページ間のナビゲーションが必要です。 1 つのコンテンツ ページを持つ単純なアプリでも、通常はナビゲーションを必要とする設定ページが存在します。 この記事では、XAML Page
をアプリに追加し、 Frame
を使用してページ間を移動する方法の基本について説明します。
重要
この例では、Microsoft Visual Studio の Blank App テンプレートを使用します。 Windows アプリ SDK/WinUI 3 アプリと UWP アプリのテンプレートには違いがあるため、アプリの種類に適したタブを選択してください。
- 適用対象: Windows アプリ SDK/WinUI3
- 重要な API: Microsoft.UI.Xaml.Controls.Frame クラス、 Microsoft.UI.Xaml.Controls.Page クラス、 Microsoft.UI.Xaml.Navigation 名前空間
1. 空のアプリを作成する
Visual Studio で空のアプリを作成するには:
- 開発コンピューターをセット アップするには、「Windows App SDK 用のツールをインストールする」を参照してください。
- Microsoft Visual Studio のスタート ウィンドウで、 新しいプロジェクトの作成または Visual Studio メニューの File>New>Project を選択します。
- 新しいプロジェクトの作成ダイアログのドロップダウン フィルターで、それぞれ C# または C++、Windows、および WinUI を選択します。
- プロジェクト テンプレートとして [空のアプリ、パッケージ (WinUI 3 in Desktop)] を選択し、[次へ] をクリックします。 そのテンプレートで、WinUI 3 ベースのユーザー インターフェイスを使用したデスクトップ アプリが作成されます。
- [ プロジェクト名 ボックスに「
BasicNavigation
」と入力し、[ Create をクリックします。 - プログラムを実行するには、メニューから Debug>Start Debugging を選択するか、F5 キーを押します。 開発用コンピューター上でソリューションをビルドして実行し、アプリがエラーなしで動作することを確認します。 空白のページが表示されます。
- デバッグを停止して Visual Studio に戻すには、アプリを終了するか、メニューから Stop Debugging をクリックします。
- テンプレートに含まれているコード例を
MainWindow.xaml
から削除し、分離コード ファイルMainWindow
します。
ヒント
詳細については、「最初の WinUI 3 (Windows アプリ SDK) プロジェクトを作成するを参照してください。
2. フレームを使用してページ間を移動する
アプリに複数のページがある場合は、 Frame を使用してページ間を移動します。 Frame
クラスは、Navigate、GoBack、GoForward、プロパティ (BackStack、ForwardStack、BackStackDepth など) をサポート。
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.xaml
は Navigate
メソッドに渡されるため、メソッドはFrame
にMainPage
を読み込みます。
アプリの初期ウィンドウへのナビゲーションが失敗すると、 NavigationFailed
イベントが発生し、このコードはイベント ハンドラーで例外をスローします。
3. 基本ページを追加する
Blank App テンプレートでは、複数のアプリ ページは作成されません。 ページ間を移動する前に、いくつかのページをアプリに追加する必要があります。
アプリに新しい項目を追加するには:
- ソリューション エクスプローラーで、
BasicNavigation
プロジェクト ノードを右クリックしてコンテキスト メニューを開きます。 - コンテキスト メニューから Add>New Item を選択します。
- [ 新しい項目の追加 ] ダイアログ ボックスで、左側のウィンドウで WinUI ノードを選択し、中央のウィンドウで [ 空白ページ (WinUI 3) を選択します。
- [ 名 ボックスに「
MainPage
」と入力し、 Add ボタンを押します。 - 手順 1 から 4. を繰り返して 2 番目のページを追加しますが、[ 名 ボックスに「
Page2
」と入力します。
これらのファイルは、 BasicNavigation
プロジェクトの一部として一覧表示されます。
C# | C++ |
---|---|
|
|
重要
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 では、次の内容が追加されます。
- Text プロパティがルート Grid の子要素として
Main Page
に設定されたpageTitle
という名前のTextBlock要素。 - ルート Gridの子要素として次のページに移動するために使用されるHyperlinkButton要素。
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
内のHyperlinkButton
のClick
イベント ハンドラーがFrame.Navigate(typeof(Page2))
を呼び出すと、Frame
はPage2.xaml
の内容を表示します。
ページがフレームに読み込まれるたびに、そのページは PageStackEntry BackStack または Frame の ForwardStack に追加され、履歴と後方ナビゲーションが可能になります。
ここで、 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
分離コード ファイルで、HyperlinkButton のClick
イベントを処理して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
内のHyperlinkButton
のClick
イベントがFrame.Navigate(typeof(Page2), name.Text)
を呼び出すと、name.Text
プロパティがPage2
に渡され、ページに表示されるメッセージにイベント データの値が使用されます。
5. ページをキャッシュする
ページのコンテンツと状態は既定ではキャッシュされないため、情報をキャッシュする場合は、アプリの各ページで有効にする必要があります。
基本的なピア ツー ピアの例では、Page2
の [Click to go to page 1
] リンクをクリックすると、MainPage
のTextBox
(およびその他のフィールド) が既定の状態に設定されます。 これを回避する方法の 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);
}
ページ間を移動すると、ページが左右にスライドします。これにより、この切り替えにより自然な感覚が得られ、ページ間の接続が強化されます。
関連記事
Windows developer