次の方法で共有


NavigationView

NavigationView コントロールでは、ご利用のアプリの最上位のナビゲーションが提供されます。 これは、さまざまな画面サイズに適応し、上部のナビゲーション スタイルと左側のナビゲーション スタイルの両方をサポートしています。

上部のナビゲーション左側のナビゲーション
NavigationView では、上部と左側の両方のナビゲーション ペインやナビゲーション メニューがサポートされます

これは適切なコントロールですか?

NavigationView は次の場合に役に立つアダプティブ ナビゲーション コントロールです。

  • ご利用のアプリ全体で一貫性のあるナビゲーション エクスペリエンスを提供する。
  • 小さいウィンドウの画面領域を節約する。
  • 多くのナビゲーション カテゴリへのアクセスを整理する。

その他のナビゲーション パターンについては、ナビゲーション デザインの基本に関するページを参照してください。

UWP と WinUI 2

重要

この記事の情報と例は、Windows アプリ SDKWinUI 3 を使用するアプリ向けに最適化されていますが、一般に WinUI 2 を使用する UWP アプリに適用されます。 プラットフォーム固有の情報と例については、UWP API リファレンスを参照してください。

このセクションには、UWP または WinUI 2 アプリでコントロールを使用するために必要な情報が含まれています。

UWP アプリの NavigationView コントロールは、WinUI 2 の一部として含まれています。 インストール手順などの詳細については、「WinUI 2」を参照してください。 このコントロールの API は、Windows.UI.Xaml.ControlsMicrosoft.UI.Xaml.Controls 名前空間の両方に存在します。

最新の WinUI 2 を使用して、すべてのコントロールの最新のスタイル、テンプレート、および機能を取得することをお勧めします。 上部階層型のナビゲーションなど、NavigationView の一部の機能には、Windows 10 バージョン 1809 (SDK 17763) 以降、または WinUI 2が必要です。

WinUI 2 でこの記事のコードを使用するには、XAML のエイリアスを使って (ここでは muxc を使用)、プロジェクトに含まれる Windows UI ライブラリ API を表します。 詳細については、「WinUI 2 の概要」を参照してください。

xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

<muxc:NavigationView />

ナビゲーション ビューを作成する

WinUI 3 ギャラリー アプリには、ほとんどの WinUI 3 コントロールと機能の対話型の例が含まれています。 Microsoft Store からアプリを入手するか、GitHub でソース コードを取得します。

次の例は、XAML でシンプルなナビゲーション ビューを作成する方法を示しています。

<NavigationView>
    <NavigationView.MenuItems>
        <NavigationViewItem Content="Nav Item A"/>
        <NavigationViewItem Content="Nav Item B"/>
        <NavigationViewItem Content="Nav Item C"/>
    </NavigationView.MenuItems>

    <Frame x:Name="ContentFrame"/>
</NavigationView>

表示モード

PaneDisplayMode プロパティを使用すれば、NavigationView でさまざまなナビゲーション スタイルまたは表示モードを構成することができます。

ペインはコンテンツの上に配置されます。
PaneDisplayMode="Top"

上部のナビゲーションの例

次の場合に上部ナビゲーションをお勧めします。

  • 同じ重要度の最上位ナビゲーション カテゴリが 5 個以下であり、ドロップダウン オーバーフロー メニューとなる追加の最上位ナビゲーション カテゴリはいずれも、それほど重要ではないと考えられる。
  • 画面上にナビゲーション オプションをすべて表示する必要がある。
  • ご利用のアプリのコンテンツ用にスペースを追加したい。
  • アイコンでは、ご利用のアプリのナビゲーション カテゴリを明確に説明できない。

ペインはコンテンツの左側に展開および配置されます。
PaneDisplayMode="Left"

展開された左側のナビゲーションのウィンドウの例

次の場合に左側のナビゲーションをお勧めします。

  • 同じ重要度の最上位ナビゲーション カテゴリが 5 から 10 個ある。
  • ナビゲーション カテゴリ以外のアプリ コンテンツ用のスペースを少なくして、ナビゲーション カテゴリを非常に目立つようにする。

LeftCompact

ウィンドウは開かれるまでアイコンのみを表示し、ウィンドウはコンテンツの左側に配置されます。 開くと、ペインはコンテンツをオーバーレイします。
PaneDisplayMode="LeftCompact"

コンパクトな左側のナビゲーションのウィンドウの例

LeftMinimal

ウィンドウが開かれるまで、メニュー ボタンのみが表示されます。 開くと、ペインはコンテンツの左側をオーバーレイします。
PaneDisplayMode="LeftMinimal"

最小化されている左側のナビゲーションのウィンドウの例

Auto

既定では、PaneDisplayMode は Auto に設定されます。 Auto モードでは、NavigationView は、ウィンドウが狭いときは LeftMinimalLeftCompact の間で適応し、ウィンドウが広くなると Left に適応します。 詳細については、「アダプティブ動作」セクションを参照してください。

左側のナビゲーションの既定のアダプティブ動作
NavigationView の既定のアダプティブ動作

構造

これらのイメージは、上部または左側のナビゲーションが構成されている場合の、ウィンドウ、ヘッダー、およびコントロールのコンテンツ領域のレイアウトを示します。

上部の NavigationView レイアウト
上部のナビゲーションのレイアウト

左側の NavigationView レイアウト
左側のナビゲーションのレイアウト

ウィンドウ

PaneDisplayMode プロパティを使用すると、コンテンツの上またはコンテンツの左側にウィンドウを配置できます。

NavigationView ウィンドウには、次のものを含めることができます。

  • NavigationViewItem オブジェクト。 特定のページに移動するためのナビゲーション項目。
  • NavigationViewItemSeparator オブジェクト。 ナビゲーション項目をグループ化するための区切り記号。 Opacity プロパティを 0 に設定して区切り記号を空白としてレンダリングします。
  • NavigationViewItemHeader オブジェクト。 項目グループへのラベル付けのためのヘッダー。
  • オプションの AutoSuggestBox を含めると、アプリ レベルの検索が可能になります。 コントロールを NavigationView.AutoSuggestBox プロパティに割り当てます。
  • アプリ設定のエントリ ポイント (オプション)。 設定項目を非表示にするには、IsSettingsVisible プロパティを false に設定します。

また、左側のウィンドウには次のものが含まれています。

  • ウィンドウの開閉を切り替えるメニュー ボタン。 IsPaneToggleButtonVisible プロパティを使うと、ウィンドウが開いたとき、大きなアプリ ウィンドウで、このボタンを非表示にすることを選択できます。

NavigationView ナビゲーション ビューには、ペインの左上隅に配置された [戻る] ボタンがあります。 ただし、これを使用しても、後方ナビゲーションの処理と、バック スタックへのコンテンツの追加は自動的には行われません。 前に戻る処理を有効にするには、「後方ナビゲーション」セクションを参照してください。

ウィンドウが上部または左側に配置された場合の詳細なウィンドウ構造を以下に示します。

上部のナビゲーションのウィンドウ

NavigationView の上部ペインの構造

  1. ヘッダー
  2. ナビゲーション項目
  3. 区切り記号
  4. AutoSuggestBox (オプション)
  5. [設定] ボタン (オプション)

左側のナビゲーションのウィンドウ

NavigationView の左側ペインの構造

  1. メニュー ボタン
  2. ナビゲーション項目
  3. 区切り記号
  4. ヘッダー
  5. AutoSuggestBox (オプション)
  6. [設定] ボタン (オプション)

FooterMenuItems を使用すると、ナビゲーション ペインの最後にナビゲーション項目を配置できるのに対し、MenuItems プロパティを使用すると、ペインの先頭に項目が配置されます。

FooterMenuItems は、既定では Settings 項目の前に表示されます。 Settings 項目は、IsSettingsVisible プロパティを使用して切り替えることもできます。

FooterMenuItems には Navigation 項目だけを配置する必要があります。ペインのフッターと位置を合わせる必要がある他のコンテンツは、PaneFooter に配置する必要があります。

NavigationView に FooterMenuItems を追加する方法の例については、「FooterMenuItems クラス」を参照してください。

以下に示す画像は、フッター メニューに [アカウント][カート][ヘルプ] の各ナビゲーション項目が含まれる NavigationView です。

FooterMenuItems が含まれる NavigationView

PaneFooter プロパティに自由形式のコンテンツを追加すると、それをウィンドウのフッターに配置することができます。

ペインのフッターの上部のナビゲーション
上部のウィンドウのフッター

ペインのフッターの左側のナビゲーション
左側のウィンドウのフッター

ウィンドウのタイトルとヘッダー

PaneTitle プロパティを設定することで、ウィンドウのヘッダー領域にテキスト コンテンツを配置できます。 このプロパティは文字列を取り、メニュー ボタンの横にテキストを表示します。

画像やロゴなどのテキスト以外のコンテンツを追加するには、PaneHeader プロパティに追加することで、ウィンドウのヘッダーに任意の要素を配置できます。

PaneTitle と PaneHeader の両方を設定した場合、コンテンツはメニュー ボタンの横に水平に積み上げられ、PaneTitle はメニュー ボタンに最も近くなります。

ペインのヘッダーの上部のナビゲーション
上部のウィンドウのヘッダー

ペインのヘッダーの左側のナビゲーション
左側のウィンドウのヘッダー

ウィンドウのコンテンツ

自由形式のコンテンツは、PaneCustomContent プロパティに追加することでウィンドウに配置できます。

ペインのカスタム コンテンツの上部のナビゲーション
上部のウィンドウのカスタム コンテンツ

ペインのカスタム コンテンツの左側のナビゲーション
左側のウィンドウのカスタム コンテンツ

Header プロパティを設定することで、ページのタイトルを追加できます。

NavigationView のヘッダー領域の例
NavigationView のヘッダー

ヘッダー領域は、左側のウィンドウ位置では移動ボタンともに垂直方向に揃えられ、上部のウィンドウ位置ではウィンドウの下に置かれます。 その高さは、52 ピクセルで固定です。 その目的は、選択されたナビゲーション カテゴリのページ タイトルを保持することです。 ヘッダーはページ上部に固定され、コンテンツ領域のスクロール クリッピング ポイントとして機能します。

ヘッダーは、NavigationView が Minimal 表示モードのときはいつも表示されます。 ウィンドウの幅をもっと広げて使用される他のモードでは、ヘッダーを非表示にすることもできます。 ヘッダーを非表示にするには、AlwaysShowHeader プロパティを false に設定します。

コンテンツ

NavigationView のコンテンツ領域の例
NavigationView のコンテンツ

コンテンツ領域には、選択されたナビゲーション カテゴリのほとんどの情報が表示されます。

NavigationView がMinimal モードの場合はコンテンツ領域に 12 ピクセルの余白を設定し、それ以外の場合は 24 ピクセルの余白を設定することをお勧めします。

アダプティブ動作

既定では、利用可能な画面領域の大きさに基づいて、自動的に NavigationView の表示モードが変化します。 CompactModeThresholdWidth プロパティおよび ExpandedModeThresholdWidth プロパティでは、表示モードが変更されるブレークポイントが指定されます。 これらの値を変更することで、アダプティブ表示モードの動作をカスタマイズできます。

既定

PaneDisplayMode を既定値である Auto に設定すると、アダプティブ動作は次のようになります。

  • ウィンドウ幅が広い場合 (1008 ピクセル以上)、展開された左側のウィンドウが表示されます。
  • ウィンドウ幅が中くらいの場合 (641 ピクセルから 1007 ピクセル)、左側 (アイコンのみ) のナビゲーション ペイン (LeftCompact) が表示されます。
  • ウィンドウ幅が狭い場合 (640 ピクセル以下)、メニュー ボタン (LeftMinimal) のみが表示されます。

アダプティブ動作に対応するウィンドウ サイズの詳細については、「画面のサイズとブレークポイント」を参照してください。

左側のナビゲーションの既定のアダプティブ動作
NavigationView の既定のアダプティブ動作

最小

2 つ目の一般的なアダプティブ パターンは、ウィンドウ幅が広い場合は展開された左側のウィンドウを使用し、ウィンドウ幅が中くらいまたは狭い場合はメニュー ボタンのみを使用するというものです。

これは次の場合にお勧めします。

  • ウィンドウ幅が小さい場合にアプリ コンテンツ用のスペースを広く確保したい。
  • アイコンでは、ナビゲーション カテゴリを明確に表すことができない。

左側のナビゲーションの最小アダプティブ動作
NavigationView の "最小" アダプティブ動作

この動作を設定するには、ウィンドウを折りたたむときの幅を CompactModeThresholdWidth に設定します。 ここでは、既定の 640 から 1007 に変更されています。 また、値が競合しないように ExpandedModeThresholdWidth を設定する必要があります。

<NavigationView CompactModeThresholdWidth="1007" ExpandedModeThresholdWidth="1007"/>

コンパクト

3 つ目の一般的なアダプティブ パターンは、ウィンドウ幅が広い場合は展開された左側のウィンドウを使用し、ウィンドウ幅が中くらいの場合と狭い場合では LeftCompact (アイコンのみ) ナビゲーション ウィンドウを使用するというものです。

これは次の場合にお勧めします。

  • 常にすべてのナビゲーション オプションを画面に表示することが重要。
  • アイコンで、ナビゲーション カテゴリを明確に表すことができる。

左側のナビゲーションのコンパクト アダプティブ動作
NavigationView の "コンパクト" アダプティブ動作

この動作を構成するには、CompactModeThresholdWidth を 0 に設定します。

<NavigationView CompactModeThresholdWidth="0"/>

アダプティブ動作なし

自動アダプティブ動作を無効にするには、PaneDisplayMode を Auto 以外の値に設定します。 ここでは、LeftMinimal に設定されているので、ウィンドウの幅に関係なくメニュー ボタンのみが表示されます。

左側のナビゲーションのアダプティブ動作なし
PaneDisplayMode が LeftMinimal に設定された NavigationView

<NavigationView PaneDisplayMode="LeftMinimal" />

表示モード」セクションで既に説明したように、ウィンドウが常に上部にある状態、常に展開された状態、常にコンパクトの状態、または常に最小の状態になるように設定することができます。 ご自分のアプリ コード内で表示モードを自身で管理することもできます。 この例については、次のセクションで示します。

上部のナビゲーションから左側のナビゲーションへ

ご利用のアプリで上部のナビゲーションを使用すると、ウィンドウ幅が狭くなるにつれてナビゲーション項目がオーバーフロー メニューに折りたたまれます。 ご利用のアプリのウィンドウ幅が狭い場合は、すべての項目をオーバーフロー メニューに折りたたむのではなく、PaneDisplayMode を Top から LeftMinimal ナビゲーションに切り替える方がユーザー エクスペリエンスが向上します。

次の場合、ウィンドウ サイズが大きいときは上部のナビゲーションを使用し、ウィンドウ サイズが小さいときは左側のナビゲーションを使用することをお勧めします。

  • 最上位ナビゲーション カテゴリのセット内の 1 つが画面に収まらない場合に、左側のナビゲーションに折りたたんで重要度を同じにして一緒に表示される必要のある同じ重要度のセットがある。
  • 小さいウィンドウ サイズでできるだけ多くのコンテンツスペースを確保したい。

この例では、VisualStateManagerAdaptiveTrigger.MinWindowWidth プロパティを使用して、TopLeftMinimal ナビゲーションを切り替える方法を示します。

上部または左側のアダプティブ動作 1 の例

<Grid>
    <NavigationView x:Name="NavigationViewControl" >
        <NavigationView.MenuItems>
            <NavigationViewItem Content="A" x:Name="A" />
            <NavigationViewItem Content="B" x:Name="B" />
            <NavigationViewItem Content="C" x:Name="C" />
        </NavigationView.MenuItems>
    </NavigationView>

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState>
                <VisualState.StateTriggers>
                    <AdaptiveTrigger
                        MinWindowWidth="{x:Bind NavigationViewControl.CompactModeThresholdWidth}" />
                </VisualState.StateTriggers>

                <VisualState.Setters>
                    <Setter Target="NavigationViewControl.PaneDisplayMode" Value="Top"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

ヒント

AdaptiveTrigger.MinWindowWidth を使用すると、ウィンドウの幅が指定された最小幅よりも広くなったときに表示状態がトリガーされます。 つまり、既定の XAML によって狭いウィンドウが定義され、VisualState によってウィンドウが広くなったときに適用する変更が定義されます。 NavigationView の既定の PaneDisplayMode は Auto なので、ウィンドウの幅が CompactModeThresholdWidth 以下のときは LeftMinimal ナビゲーションが使用されます。 ウィンドウが広くなると、VisualState によって既定値がオーバーライドされ、Top ナビゲーションが使用されます。

NavigationView では、どのナビゲーション タスクも自動的に実行されません。 ユーザーがナビゲーション項目をタップすると、NavigationView ではその項目が選択済みとして表示され、ItemInvoked イベントが発生します。 タップによって新しい項目が選択されると、SelectionChanged イベントも発生します。

どちらのイベントを処理しても、要求されたナビゲーションに関連するタスクを実行できます。 どちらを処理する必要があるかは、ご利用のアプリに求める動作によって異なります。 通常は、要求されたページに移動し、これらのイベントに応じて NavigationView のヘッダーを更新します。

  • ItemInvoked は、ユーザーがナビゲーション項目をタップするたびに、それが既に選択されている場合でも発生します。 (項目は、マウス、キーボード、またはその他の入力を使用して同等の操作で呼び出すこともできます。詳細については、「入力と操作」を参照してください)。ItemInvoked ハンドラー内を移動すると、既定ではページが再読み込みされ、重複エントリがナビゲーション スタックに追加されます。 項目が呼び出されたときに移動する場合は、ページの再読み込みを禁止するか、またはページが再読み込みされるときにナビゲーション バックスタック内に重複エントリが決して作成されないようにする必要があります。 (コード例を参照してください)。
  • SelectionChanged は、現在選択されていない項目をユーザーが呼び出すことで発生させることも、選択された項目をプログラムで変更することによって発生させることもできます。 ユーザーが項目を呼び出したために選択の変更が発生した場合は、最初に ItemInvoked イベントが発生します。 選択の変更がプログラムによるものである場合、ItemInvoked は発生しません。

すべてのナビゲーション項目は、MenuItems または FooterMenuItems の一部であるかどうかにかかわらず、同じ選択モデルの一部です。 選択できるナビゲーション項目は、一度に 1 つだけです。

逆方向のナビゲーション

NavigationView には組み込みの [戻る] ボタンがありますが、前方ナビゲーションと同様に、後方ナビゲーションは自動的には実行されません。 ユーザーが [戻る] ボタンをタップすると、BackRequested イベントが発生します。 このイベントを処理して、後方ナビゲーションを実行します。 詳細については、ナビゲーション履歴と後方ナビゲーションに関するページを参照してください。

Minimal または Compact モードでは、NavigationView Pane はポップアップとして開きます。 この場合、[戻る] ボタンをクリックすると、Pane が閉じられ、代わりに PaneClosing イベントが発生します。

以下のプロパティを設定することで、[戻る] ボタンを非表示または無効にすることができます。

  • IsBackButtonVisible: [戻る] ボタンを表示および非表示にするために使用します。 このプロパティは NavigationViewBackButtonVisible 列挙体の値を取り、既定では Auto に設定されています。 ボタンが折りたたまれると、このボタン用のスペースはレイアウト内に確保されません。
  • IsBackEnabled: [戻る] ボタンを有効または無効にするために使用します。 このプロパティは、ご利用のナビゲーション フレームの CanGoBack プロパティにデータ バインドすることができます。 IsBackEnabledfalse の場合、BackRequested は発生しません。

左側のナビゲーション ペインの NavigationView の [戻る] ボタン
左側のナビゲーション ウィンドウの [戻る] ボタン

上部ナビゲーション ペインの NavigationView の [戻る] ボタン
上部ナビゲーション ウィンドウの [戻る] ボタン

コードの例

この例では、ウィンドウ サイズが大きい場合の上部のナビゲーション ウィンドウとウィンドウ サイズが小さい場合の左側のナビゲーション ウィンドウの両方で NavigationView を使用する方法を示します。 これは、VisualStateManager で上部のナビゲーション設定を削除することにより、左側のみのナビゲーションに適応させることができます。

この例は、多くのシナリオで機能するナビゲーション データを設定するための一般的な方法を示しています。 この例では、移動先のページの完全な型名を (NavigationViewItem のタグに) 最初に格納します。 イベント ハンドラーでは、その値のボックス化を解除し、それをType(C#) または Windows::UI::Xaml::Interop::TypeName(C++/WinRT) オブジェクトに変換し、それを使用して目的のページに移動します。 これにより、単体テストを作成して、タグ内の値が有効な型であることを確認できます (「C++/WinRT を使用した IInspectable への値のボックス化とボックス化解除」も参照してください)。 また、NavigationView の [戻る] ボタンを使用して後方ナビゲーションを実装する方法についても示します。

このコードでは、移動先である次の名前を含むページが、ご利用のアプリに含まれていることを前提としています。HomePageAppsPageGamesPageMusicPageMyContentPage、および SettingsPage。 これらのページのコードは示されていません。

<Page ... >
 <Grid>
     <NavigationView x:Name="NavView"
                     Loaded="NavView_Loaded"
                     ItemInvoked="NavView_ItemInvoked"
                     BackRequested="NavView_BackRequested">
         <NavigationView.MenuItems>
             <NavigationViewItem Tag="NavigationViewDemo.HomePage" Icon="Home" Content="Home"/>
             <NavigationViewItemSeparator/>
             <NavigationViewItemHeader x:Name="MainPagesHeader"
                                       Content="Main pages"/>
             <NavigationViewItem Tag="NavigationViewDemo.AppsPage" Content="Apps">
                 <NavigationViewItem.Icon>
                     <FontIcon Glyph="&#xEB3C;"/>
                 </NavigationViewItem.Icon>
             </NavigationViewItem>
             <NavigationViewItem Tag="NavigationViewDemo.GamesPage" Content="Games">
                 <NavigationViewItem.Icon>
                     <FontIcon Glyph="&#xE7FC;"/>
                 </NavigationViewItem.Icon>
             </NavigationViewItem>
             <NavigationViewItem Tag="NavigationViewDemo.MusicPage" Icon="Audio" Content="Music"/>
         </NavigationView.MenuItems>

         <NavigationView.AutoSuggestBox>
             <!-- See AutoSuggestBox documentation for
              more info about how to implement search. -->
             <AutoSuggestBox x:Name="NavViewSearchBox" QueryIcon="Find"/>
         </NavigationView.AutoSuggestBox>

         <ScrollViewer>
             <Frame x:Name="ContentFrame" IsTabStop="True"
                NavigationFailed="ContentFrame_NavigationFailed"/>
         </ScrollViewer>
     </NavigationView>

     <VisualStateManager.VisualStateGroups>
         <VisualStateGroup>
             <VisualState>
                 <VisualState.StateTriggers>
                     <AdaptiveTrigger
                     MinWindowWidth="{x:Bind NavViewCompactModeThresholdWidth}"/>
                 </VisualState.StateTriggers>
                 <VisualState.Setters>
                     <!-- Remove the next 3 lines for left-only navigation. -->
                     <Setter Target="NavView.PaneDisplayMode" Value="Top"/>
                     <Setter Target="NavViewSearchBox.Width" Value="200"/>
                     <Setter Target="MainPagesHeader.Visibility" Value="Collapsed"/>
                     <!-- Leave the next line for left-only navigation. -->
                     <Setter Target="ContentFrame.Padding" Value="24,0,24,24"/>
                 </VisualState.Setters>
             </VisualState>
         </VisualStateGroup>
     </VisualStateManager.VisualStateGroups>
 </Grid>
</Page>
private double NavViewCompactModeThresholdWidth { get { return NavView.CompactModeThresholdWidth; } }

private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
    throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

private void NavView_Loaded(object sender, RoutedEventArgs e)
{
    // You can also add items in code.
    NavView.MenuItems.Add(new NavigationViewItemSeparator());
    NavView.MenuItems.Add(new NavigationViewItem
    {
        Content = "My content",
        Icon = new SymbolIcon((Symbol)0xF1AD),
        Tag = "NavigationViewDemo.MyContentPage"
    });

    // Add handler for ContentFrame navigation.
    ContentFrame.Navigated += On_Navigated;

    // NavView doesn't load any page by default, so load home page.
    NavView.SelectedItem = NavView.MenuItems[0];
    // If navigation occurs on SelectionChanged, this isn't needed.
    // Because we use ItemInvoked to navigate, we need to call Navigate
    // here to load the home page.
    NavView_Navigate(typeof(HomePage), new EntranceNavigationTransitionInfo());
}

private void NavView_ItemInvoked(NavigationView sender,
                                 NavigationViewItemInvokedEventArgs args)
{
    if (args.IsSettingsInvoked == true)
    {
        NavView_Navigate(typeof(SettingsPage), args.RecommendedNavigationTransitionInfo);
    }
    else if (args.InvokedItemContainer != null)
    {
        Type navPageType = Type.GetType(args.InvokedItemContainer.Tag.ToString());
        NavView_Navigate(navPageType, args.RecommendedNavigationTransitionInfo);
    }
}

// NavView_SelectionChanged is not used in this example, but is shown for completeness.
// You will typically handle either ItemInvoked or SelectionChanged to perform navigation,
// but not both.
private void NavView_SelectionChanged(NavigationView sender,
                                      NavigationViewSelectionChangedEventArgs args)
{
    if (args.IsSettingsSelected == true)
    {
        NavView_Navigate(typeof(SettingsPage), args.RecommendedNavigationTransitionInfo);
    }
    else if (args.SelectedItemContainer != null)
    {
        Type navPageType = Type.GetType(args.SelectedItemContainer.Tag.ToString());
        NavView_Navigate(navPageType, args.RecommendedNavigationTransitionInfo);
    }
}

private void NavView_Navigate(
    Type navPageType,
    NavigationTransitionInfo transitionInfo)
{
    // Get the page type before navigation so you can prevent duplicate
    // entries in the backstack.
    Type preNavPageType = ContentFrame.CurrentSourcePageType;

    // Only navigate if the selected page isn't currently loaded.
    if (navPageType is not null && !Type.Equals(preNavPageType, navPageType))
    {
        ContentFrame.Navigate(navPageType, null, transitionInfo);
    }
}

private void NavView_BackRequested(NavigationView sender,
                                   NavigationViewBackRequestedEventArgs args)
{
    TryGoBack();
}

private bool TryGoBack()
{
    if (!ContentFrame.CanGoBack)
        return false;

    // Don't go back if the nav pane is overlayed.
    if (NavView.IsPaneOpen &&
        (NavView.DisplayMode == NavigationViewDisplayMode.Compact ||
         NavView.DisplayMode == NavigationViewDisplayMode.Minimal))
        return false;

    ContentFrame.GoBack();
    return true;
}

private void On_Navigated(object sender, NavigationEventArgs e)
{
    NavView.IsBackEnabled = ContentFrame.CanGoBack;

    if (ContentFrame.SourcePageType == typeof(SettingsPage))
    {
        // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag.
        NavView.SelectedItem = (NavigationViewItem)NavView.SettingsItem;
        NavView.Header = "Settings";
    }
    else if (ContentFrame.SourcePageType != null)
    {
        // Select the nav view item that corresponds to the page being navigated to.
        NavView.SelectedItem = NavView.MenuItems
                    .OfType<NavigationViewItem>()
                    .First(i => i.Tag.Equals(ContentFrame.SourcePageType.FullName.ToString()));

        NavView.Header =
            ((NavigationViewItem)NavView.SelectedItem)?.Content?.ToString();

    }
}
// MainPage.idl
runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
{
    ...
    Double NavViewCompactModeThresholdWidth{ get; };
}

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


// MainPage.h
#pragma once

#include "MainPage.g.h"

namespace muxc
{
    using namespace winrt::Microsoft::UI::Xaml::Controls;
};

namespace winrt::NavigationViewDemo::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
        MainPage();

        double NavViewCompactModeThresholdWidth();
        void ContentFrame_NavigationFailed(
            Windows::Foundation::IInspectable const& /* sender */,
            Microsoft::UI::Xaml::Navigation::NavigationFailedEventArgs const& args);
        void NavView_Loaded(
            Windows::Foundation::IInspectable const& /* sender */,
            Microsoft::UI::Xaml::RoutedEventArgs const& /* args */);
        void NavView_ItemInvoked(
            Windows::Foundation::IInspectable const& /* sender */,
            muxc::NavigationViewItemInvokedEventArgs const& args);

        // NavView_SelectionChanged is not used in this example, but is shown for completeness.
        // You'll typically handle either ItemInvoked or SelectionChanged to perform navigation,
        // but not both.
        void NavView_SelectionChanged(
            muxc::NavigationView const& /* sender */,
            muxc::NavigationViewSelectionChangedEventArgs const& args);
        void NavView_Navigate(
            Windows::UI::Xaml::Interop::TypeName navPageType,
            Microsoft::UI::Xaml::Media::Animation::NavigationTransitionInfo const& transitionInfo);
        void NavView_BackRequested(
            muxc::NavigationView const& /* sender */,
            muxc::NavigationViewBackRequestedEventArgs const& /* args */);
        void On_Navigated(
            Windows::Foundation::IInspectable const& /* sender */,
            Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& args);
        bool TryGoBack();

    private:

    };
}

namespace winrt::NavigationViewDemo::factory_implementation
{
    struct MainPage : MainPageT<MainPage, implementation::MainPage>
    {
    };
}

// MainPage.cpp
#include "pch.h"
#include "MainPage.xaml.h"
#if __has_include("MainPage.g.cpp")
#include "MainPage.g.cpp"
#endif

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

namespace winrt::NavigationViewDemo::implementation
{
    MainPage::MainPage()
    {
        InitializeComponent();
    }

    double MainPage::NavViewCompactModeThresholdWidth()
    {
        return NavView().CompactModeThresholdWidth();
    }

    void MainPage::ContentFrame_NavigationFailed(
        Windows::Foundation::IInspectable const& /* sender */,
        Microsoft::UI::Xaml::Navigation::NavigationFailedEventArgs const& args)
    {
        throw winrt::hresult_error(
            E_FAIL, winrt::hstring(L"Failed to load Page ") + args.SourcePageType().Name);
    }

    void MainPage::NavView_Loaded(
        Windows::Foundation::IInspectable const& /* sender */,
        Microsoft::UI::Xaml::RoutedEventArgs const& /* args */)
    {
        // You can also add items in code.
        NavView().MenuItems().Append(muxc::NavigationViewItemSeparator());
        muxc::NavigationViewItem navigationViewItem;
        navigationViewItem.Content(winrt::box_value(L"My content"));
        navigationViewItem.Icon(muxc::SymbolIcon(static_cast<muxc::Symbol>(0xF1AD)));
        navigationViewItem.Tag(winrt::box_value(L"NavigationViewDemo.MyContentPage"));
        NavView().MenuItems().Append(navigationViewItem);

        // Add handler for ContentFrame navigation.
        ContentFrame().Navigated({ this, &MainPage::On_Navigated });

        // NavView doesn't load any page by default, so load home page.
        NavView().SelectedItem(NavView().MenuItems().GetAt(0));
        // If navigation occurs on SelectionChanged, then this isn't needed.
        // Because we use ItemInvoked to navigate, we need to call Navigate
        // here to load the home page.
        NavView_Navigate(winrt::xaml_typename<NavigationViewDemo::HomePage>(),
            Microsoft::UI::Xaml::Media::Animation::EntranceNavigationTransitionInfo());
    }

    void MainPage::NavView_ItemInvoked(
        Windows::Foundation::IInspectable const& /* sender */,
        muxc::NavigationViewItemInvokedEventArgs const& args)
    {
        if (args.IsSettingsInvoked())
        {
            NavView_Navigate(winrt::xaml_typename<NavigationViewDemo::SettingsPage>(),
                args.RecommendedNavigationTransitionInfo());
        }
        else if (args.InvokedItemContainer())
        {
            Windows::UI::Xaml::Interop::TypeName pageTypeName;
            pageTypeName.Name = unbox_value<hstring>(args.InvokedItemContainer().Tag());
            pageTypeName.Kind = Windows::UI::Xaml::Interop::TypeKind::Primitive;
            NavView_Navigate(pageTypeName, args.RecommendedNavigationTransitionInfo());
        }
    }

    // NavView_SelectionChanged is not used in this example, but is shown for completeness.
    // You will typically handle either ItemInvoked or SelectionChanged to perform navigation,
    // but not both.
    void MainPage::NavView_SelectionChanged(
        muxc::NavigationView const& /* sender */,
        muxc::NavigationViewSelectionChangedEventArgs const& args)
    {
        if (args.IsSettingsSelected())
        {
            NavView_Navigate(winrt::xaml_typename<NavigationViewDemo::SettingsPage>(),
                args.RecommendedNavigationTransitionInfo());
        }
        else if (args.SelectedItemContainer())
        {
            Windows::UI::Xaml::Interop::TypeName pageTypeName;
            pageTypeName.Name = unbox_value<hstring>(args.SelectedItemContainer().Tag());
            pageTypeName.Kind = Windows::UI::Xaml::Interop::TypeKind::Primitive;
            NavView_Navigate(pageTypeName, args.RecommendedNavigationTransitionInfo());
        }
    }

    void MainPage::NavView_Navigate(
        Windows::UI::Xaml::Interop::TypeName navPageType,
        Microsoft::UI::Xaml::Media::Animation::NavigationTransitionInfo const& transitionInfo)
    {
        // Get the page type before navigation so you can prevent duplicate
        // entries in the backstack.
        Windows::UI::Xaml::Interop::TypeName preNavPageType =
            ContentFrame().CurrentSourcePageType();

        // Navigate only if the selected page isn't currently loaded.
        if (navPageType.Name != L"" && preNavPageType.Name != navPageType.Name)
        {
            ContentFrame().Navigate(navPageType, nullptr, transitionInfo);
        }
    }

    void MainPage::NavView_BackRequested(
        muxc::NavigationView const& /* sender */,
        muxc::NavigationViewBackRequestedEventArgs const& /* args */)
    {
        TryGoBack();
    }

    bool MainPage::TryGoBack()
    {
        if (!ContentFrame().CanGoBack())
            return false;
        // Don't go back if the nav pane is overlayed.
        if (NavView().IsPaneOpen() &&
            (NavView().DisplayMode() == muxc::NavigationViewDisplayMode::Compact ||
                NavView().DisplayMode() == muxc::NavigationViewDisplayMode::Minimal))
            return false;
        ContentFrame().GoBack();
        return true;
    }

    void MainPage::On_Navigated(
        Windows::Foundation::IInspectable const& /* sender */,
        Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& args)
    {
        NavView().IsBackEnabled(ContentFrame().CanGoBack());

        if (ContentFrame().SourcePageType().Name ==
            winrt::xaml_typename<NavigationViewDemo::SettingsPage>().Name)
        {
            // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag.
            NavView().SelectedItem(NavView().SettingsItem().as<muxc::NavigationViewItem>());
            NavView().Header(winrt::box_value(L"Settings"));
        }
        else if (ContentFrame().SourcePageType().Name != L"")
        {
            for (auto&& eachMenuItem : NavView().MenuItems())
            {
                auto navigationViewItem =
                    eachMenuItem.try_as<muxc::NavigationViewItem>();
                {
                    if (navigationViewItem)
                    {
                        winrt::hstring hstringValue =
                            winrt::unbox_value_or<winrt::hstring>(
                                navigationViewItem.Tag(), L"");
                        if (hstringValue == ContentFrame().SourcePageType().Name)
                        {
                            NavView().SelectedItem(navigationViewItem);
                            NavView().Header(navigationViewItem.Content());
                        }
                    }
                }
            }
        }
    }
}

階層型ナビゲーション

アプリによっては、ナビゲーション項目の単純なリストだけでは対応しきれない、より複雑な階層構造が存在する場合があります。 最上位レベルのナビゲーション項目を使用してページのカテゴリを表示し、特定のページを子項目で表示することができます。 これは、他のページにリンクされているだけのハブスタイルのページがある場合にも便利です。 このような場合には、階層型の NavigationView を作成する必要があります。

入れ子になったナビゲーション項目の階層型リストをペインに表示するには、NavigationViewItemMenuItems プロパティか MenuItemsSource プロパティを使用します。 各 NavigationViewItem には、他の NavigationViewItems と整理のための要素 (項目ヘッダーや区切り記号など) 含めることができます。 MenuItemsSource を使用するときに階層型リストを表示するには、ItemTemplate が NavigationViewItem になるように設定し、その MenuItemsSource プロパティを階層の次のレベルにバインドします。

NavigationViewItem には入れ子になったレベルをいくつでも含めることができますが、アプリのナビゲーション階層は浅く保つことをお勧めします。 使いやすさと理解しやすさを考慮すると、レベルは 2 つが理想的でしょう。

NavigationView では、TopLeftLeftCompact のペイン表示モードで階層が表示されます。 各ペイン表示モードで展開されたサブツリーは次のようになります。

階層構造を備えた NavigationView

マークアップでの項目の階層の追加

この例は、XAML マークアップで階層型アプリ ナビゲーションを宣言する方法を示しています。

<NavigationView>
    <NavigationView.MenuItems>
        <NavigationViewItem Content="Home" Icon="Home" ToolTipService.ToolTip="Home"/>
        <NavigationViewItem Content="Collections" Icon="Keyboard" ToolTipService.ToolTip="Collections">
            <NavigationViewItem.MenuItems>
                <NavigationViewItem Content="Notes" Icon="Page" ToolTipService.ToolTip="Notes"/>
                <NavigationViewItem Content="Mail" Icon="Mail" ToolTipService.ToolTip="Mail"/>
            </NavigationViewItem.MenuItems>
        </NavigationViewItem>
    </NavigationView.MenuItems>
</NavigationView>

データ バインディングを使用した項目の階層の追加

メニュー項目の階層を NavigationView に追加する方法

  • MenuItemsSource プロパティを階層型データにバインドする
  • 項目テンプレートを NavigationViewMenuItem として定義し、その内容をメニュー項目のラベルに設定し、その MenuItemsSource プロパティを階層の次のレベルにバインドする

この例では、Expanding イベントと Collapsed イベントも示されています。 これらのイベントは、子があるメニュー項目に対して発生します。

<Page ... >
    <Page.Resources>
        <DataTemplate x:Key="NavigationViewMenuItem" x:DataType="local:Category">
            <NavigationViewItem Content="{x:Bind Name}" MenuItemsSource="{x:Bind Children}"/>
        </DataTemplate>
    </Page.Resources>

    <Grid>
        <NavigationView x:Name="navview"
    MenuItemsSource="{x:Bind Categories, Mode=OneWay}"
    MenuItemTemplate="{StaticResource NavigationViewMenuItem}"
    ItemInvoked="{x:Bind OnItemInvoked}"
    Expanding="OnItemExpanding"
    Collapsed="OnItemCollapsed"
    PaneDisplayMode="Left">
            <StackPanel Margin="10,10,0,0">
                <TextBlock Margin="0,10,0,0" x:Name="ExpandingItemLabel" Text="Last Expanding: N/A"/>
                <TextBlock x:Name="CollapsedItemLabel" Text="Last Collapsed: N/A"/>
            </StackPanel>
        </NavigationView>
    </Grid>
</Page>
public class Category
{
    public String Name { get; set; }
    public String CategoryIcon { get; set; }
    public ObservableCollection<Category> Children { get; set; }
}

public sealed partial class HierarchicalNavigationViewDataBinding : Page
{
    public HierarchicalNavigationViewDataBinding()
    {
        this.InitializeComponent();
    }

    public ObservableCollection<Category> Categories = new ObservableCollection<Category>()
    {
        new Category(){
            Name = "Menu item 1",
            CategoryIcon = "Icon",
            Children = new ObservableCollection<Category>() {
                new Category(){
                    Name = "Menu item 2",
                    CategoryIcon = "Icon",
                    Children = new ObservableCollection<Category>() {
                        new Category() {
                            Name  = "Menu item 3",
                            CategoryIcon = "Icon",
                            Children = new ObservableCollection<Category>() {
                                new Category() { Name  = "Menu item 4", CategoryIcon = "Icon" },
                                new Category() { Name  = "Menu item 5", CategoryIcon = "Icon" }
                            }
                        }
                    }
                }
            }
        },
        new Category(){
            Name = "Menu item 6",
            CategoryIcon = "Icon",
            Children = new ObservableCollection<Category>() {
                new Category(){
                    Name = "Menu item 7",
                    CategoryIcon = "Icon",
                    Children = new ObservableCollection<Category>() {
                        new Category() { Name  = "Menu item 8", CategoryIcon = "Icon" },
                        new Category() { Name  = "Menu item 9", CategoryIcon = "Icon" }
                    }
                }
            }
        },
        new Category(){ Name = "Menu item 10", CategoryIcon = "Icon" }
    };

    private void OnItemInvoked(object sender, NavigationViewItemInvokedEventArgs e)
    {
        var clickedItem = e.InvokedItem;
        var clickedItemContainer = e.InvokedItemContainer;
    }
    private void OnItemExpanding(object sender, NavigationViewItemExpandingEventArgs e)
    {
        var nvib = e.ExpandingItemContainer;
        var name = "Last expanding: " + nvib.Content.ToString();
        ExpandingItemLabel.Text = name;
    }
    private void OnItemCollapsed(object sender, NavigationViewItemCollapsedEventArgs e)
    {
        var nvib = e.CollapsedItemContainer;
        var name = "Last collapsed: " + nvib.Content;
        CollapsedItemLabel.Text = name;
    }
}
// Category.idl
namespace HierarchicalNavigationViewDataBinding
{
    runtimeclass Category
    {
        String Name;
        String CategoryIcon;
        Windows.Foundation.Collections.IObservableVector<Category> Children;
    }
}

// Category.h
#pragma once
#include "Category.g.h"

namespace winrt::HierarchicalNavigationViewDataBinding::implementation
{
    struct Category : CategoryT<Category>
    {
        Category();
        Category(winrt::hstring name,
            winrt::hstring categoryIcon,
            Windows::Foundation::Collections::
                IObservableVector<HierarchicalNavigationViewDataBinding::Category> children);

        winrt::hstring Name();
        void Name(winrt::hstring const& value);
        winrt::hstring CategoryIcon();
        void CategoryIcon(winrt::hstring const& value);
        Windows::Foundation::Collections::
            IObservableVector<HierarchicalNavigationViewDataBinding::Category> Children();
        void Children(Windows::Foundation::Collections:
            IObservableVector<HierarchicalNavigationViewDataBinding::Category> const& value);

    private:
        winrt::hstring m_name;
        winrt::hstring m_categoryIcon;
        Windows::Foundation::Collections::
            IObservableVector<HierarchicalNavigationViewDataBinding::Category> m_children;
    };
}

// Category.cpp
#include "pch.h"
#include "Category.h"
#include "Category.g.cpp"

namespace winrt::HierarchicalNavigationViewDataBinding::implementation
{
    Category::Category()
    {
        m_children = winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    }

    Category::Category(
        winrt::hstring name,
        winrt::hstring categoryIcon,
        Windows::Foundation::Collections::
            IObservableVector<HierarchicalNavigationViewDataBinding::Category> children)
    {
        m_name = name;
        m_categoryIcon = categoryIcon;
        m_children = children;
    }

    hstring Category::Name()
    {
        return m_name;
    }

    void Category::Name(hstring const& value)
    {
        m_name = value;
    }

    hstring Category::CategoryIcon()
    {
        return m_categoryIcon;
    }

    void Category::CategoryIcon(hstring const& value)
    {
        m_categoryIcon = value;
    }

    Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category>
        Category::Children()
    {
        return m_children;
    }

    void Category::Children(
        Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category>
            const& value)
    {
        m_children = value;
    }
}

// MainPage.idl
import "Category.idl";

namespace HierarchicalNavigationViewDataBinding
{
    [default_interface]
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        Windows.Foundation.Collections.IObservableVector<Category> Categories{ get; };
    }
}

// MainPage.h
#pragma once

#include "MainPage.g.h"

namespace muxc
{
    using namespace winrt::Microsoft::UI::Xaml::Controls;
};

namespace winrt::HierarchicalNavigationViewDataBinding::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
        MainPage();

        Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category>
            Categories();

        void OnItemInvoked(muxc::NavigationView const& sender, muxc::NavigationViewItemInvokedEventArgs const& args);
        void OnItemExpanding(
            muxc::NavigationView const& sender,
            muxc::NavigationViewItemExpandingEventArgs const& args);
        void OnItemCollapsed(
            muxc::NavigationView const& sender,
            muxc::NavigationViewItemCollapsedEventArgs const& args);

    private:
        Windows::Foundation::Collections::
            IObservableVector<HierarchicalNavigationViewDataBinding::Category> m_categories;
    };
}

namespace winrt::HierarchicalNavigationViewDataBinding::factory_implementation
{
    struct MainPage : MainPageT<MainPage, implementation::MainPage>
    {
    };
}

// MainPage.cpp
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"

#include "Category.h"

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

        m_categories =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();

        auto menuItem10 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 10", L"Icon", nullptr);

        auto menuItem9 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 9", L"Icon", nullptr);
        auto menuItem8 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 8", L"Icon", nullptr);
        auto menuItem7Children =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
        menuItem7Children.Append(*menuItem9);
        menuItem7Children.Append(*menuItem8);

        auto menuItem7 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 7", L"Icon", menuItem7Children);
        auto menuItem6Children =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
        menuItem6Children.Append(*menuItem7);

        auto menuItem6 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 6", L"Icon", menuItem6Children);

        auto menuItem5 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 5", L"Icon", nullptr);
        auto menuItem4 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 4", L"Icon", nullptr);
        auto menuItem3Children =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
        menuItem3Children.Append(*menuItem5);
        menuItem3Children.Append(*menuItem4);

        auto menuItem3 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 3", L"Icon", menuItem3Children);
        auto menuItem2Children =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
        menuItem2Children.Append(*menuItem3);

        auto menuItem2 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 2", L"Icon", menuItem2Children);
        auto menuItem1Children =
            winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
        menuItem1Children.Append(*menuItem2);

        auto menuItem1 = winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
            (L"Menu item 1", L"Icon", menuItem1Children);

        m_categories.Append(*menuItem1);
        m_categories.Append(*menuItem6);
        m_categories.Append(*menuItem10);
    }

    Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category>
        MainPage::Categories()
    {
        return m_categories;
    }

    void MainPage::OnItemInvoked(
        muxc::NavigationView const& /* sender */,
        muxc::NavigationViewItemInvokedEventArgs const& args)
    {
        auto clickedItem = args.InvokedItem();
        auto clickedItemContainer = args.InvokedItemContainer();
    }

    void MainPage::OnItemExpanding(
        muxc::NavigationView const& /* sender */,
        muxc::NavigationViewItemExpandingEventArgs const& args)
    {
        auto nvib = args.ExpandingItemContainer();
        auto name = L"Last expanding: " + winrt::unbox_value<winrt::hstring>(nvib.Content());
        ExpandingItemLabel().Text(name);
    }

    void MainPage::OnItemCollapsed(
        muxc::NavigationView const& /* sender */,
        muxc::NavigationViewItemCollapsedEventArgs const& args)
    {
        auto nvib = args.CollapsedItemContainer();
        auto name = L"Last collapsed: " + winrt::unbox_value<winrt::hstring>(nvib.Content());
        CollapsedItemLabel().Text(name);
    }
}

選択

既定では、すべての項目に対して子を含めることができるほか、呼び出し、選択を行えます。

ナビゲーション オプションの階層型ツリーをユーザーに提供する場合、親項目を選択不可にすることができます。たとえば、アプリにその親項目に関連付けられたリンク先ページが存在しない場合などです。 親項目が選択可能 "である" 場合は、左展開または Top のペイン表示モードの使用をお勧めします。 LeftCompact モードでは、その呼び出しのたびにユーザーが子サブツリーを開くために親項目に移動することになります。

項目を選択すると、選択インジケーターが Left モードの場合は左端に沿って、Top モードの場合は下端に合わせて表示されます。 親項目が選択されている Left モードおよび Top モードの NavigationViews を次に示します。

親が選択された状態の Left モードの NavigationView

親が選択された状態の Top モードの NavigationView

選択した項目は、常に表示されたままとは限りません。 折りたたまれた、または展開されていないサブツリー内の子が選択された場合、最初に表示される先祖が選択済みとして表示されます。 サブツリーが展開されている場合または展開された場合、選択インジケーターは選択された項目に戻ります。

たとえば、上の図では、ユーザーがカレンダー項目を選択した後、そのサブツリーを折りたたむことができます。 この場合、カレンダーで最初に表示される先祖はアカウントなので、選択インジケーターはアカウント項目の下に表示されます。 ユーザーがサブツリーを再度展開すると、選択インジケーターはカレンダー項目に戻ります。

NavigationView では、選択インジケーターは全体で 1 つだけ表示されます。

Top と Left どちらのモードも、NavigationViewItems の矢印をクリックすると、サブツリーが展開されるか折りたたまれます。 NavigationViewItem の "別の場所" をクリックまたはタップすると、ItemInvoked イベントがトリガーされ、サブツリーも折りたたまれるか展開されます。

項目が呼び出されたときに選択インジケーターが表示されないようにするには、その項目の SelectsOnInvoked プロパティを次のように False に設定します。

<Page ...>
    <Page.Resources>
        <DataTemplate x:Key="NavigationViewMenuItem" x:DataType="local:Category">
            <NavigationViewItem Content="{x:Bind Name}"
            MenuItemsSource="{x:Bind Children}"
            SelectsOnInvoked="{x:Bind IsLeaf}"/>
        </DataTemplate>
    </Page.Resources>

    <Grid>
        <NavigationView x:Name="navview"
    MenuItemsSource="{x:Bind Categories, Mode=OneWay}"
    MenuItemTemplate="{StaticResource NavigationViewMenuItem}">
        </NavigationView>
    </Grid>
</Page>
public class Category
{
    public String Name { get; set; }
    public String CategoryIcon { get; set; }
    public ObservableCollection<Category> Children { get; set; }
    public bool IsLeaf { get; set; }
}

public sealed partial class HierarchicalNavigationViewDataBinding : Page
{
    public HierarchicalNavigationViewDataBinding()
    {
        this.InitializeComponent();
    }

    public ObservableCollection<Category> Categories = new ObservableCollection<Category>()
    {
        new Category(){
            Name = "Menu item 1",
            CategoryIcon = "Icon",
            Children = new ObservableCollection<Category>() {
                new Category(){
                    Name = "Menu item 2",
                    CategoryIcon = "Icon",
                    Children = new ObservableCollection<Category>() {
                        new Category() {
                            Name  = "Menu item 3",
                            CategoryIcon = "Icon",
                            Children = new ObservableCollection<Category>() {
                                new Category() { Name  = "Menu item 4", CategoryIcon = "Icon", IsLeaf = true },
                                new Category() { Name  = "Menu item 5", CategoryIcon = "Icon", IsLeaf = true }
                            }
                        }
                    }
                }
            }
        },
        new Category(){
            Name = "Menu item 6",
            CategoryIcon = "Icon",
            Children = new ObservableCollection<Category>() {
                new Category(){
                    Name = "Menu item 7",
                    CategoryIcon = "Icon",
                    Children = new ObservableCollection<Category>() {
                        new Category() { Name  = "Menu item 8", CategoryIcon = "Icon", IsLeaf = true },
                        new Category() { Name  = "Menu item 9", CategoryIcon = "Icon", IsLeaf = true }
                    }
                }
            }
        },
        new Category(){ Name = "Menu item 10", CategoryIcon = "Icon", IsLeaf = true }
    };
}
// Category.idl
namespace HierarchicalNavigationViewDataBinding
{
    runtimeclass Category
    {
        ...
        Boolean IsLeaf;
    }
}

// Category.h
...
struct Category : CategoryT<Category>
{
    ...
    Category(winrt::hstring name,
        winrt::hstring categoryIcon,
        Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category> children,
        bool isleaf = false);
    ...
    bool IsLeaf();
    void IsLeaf(bool value);

private:
    ...
    bool m_isleaf;
};

// Category.cpp
...
Category::Category(winrt::hstring name,
    winrt::hstring categoryIcon,
    Windows::Foundation::Collections::IObservableVector<HierarchicalNavigationViewDataBinding::Category> children,
    bool isleaf) : m_name(name), m_categoryIcon(categoryIcon), m_children(children), m_isleaf(isleaf) {}
...
bool Category::IsLeaf()
{
    return m_isleaf;
}

void Category::IsLeaf(bool value)
{
    m_isleaf = value;
}

// MainPage.h and MainPage.cpp
// Delete OnItemInvoked, OnItemExpanding, and OnItemCollapsed.

// MainPage.cpp
...
MainPage::MainPage()
{
    InitializeComponent();

    m_categories = winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();

    auto menuItem10 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 10", L"Icon", nullptr, true);

    auto menuItem9 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 9", L"Icon", nullptr, true);
    auto menuItem8 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 8", L"Icon", nullptr, true);
    auto menuItem7Children =
        winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    menuItem7Children.Append(*menuItem9);
    menuItem7Children.Append(*menuItem8);

    auto menuItem7 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 7", L"Icon", menuItem7Children);
    auto menuItem6Children =
        winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    menuItem6Children.Append(*menuItem7);

    auto menuItem6 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 6", L"Icon", menuItem6Children);

    auto menuItem5 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 5", L"Icon", nullptr, true);
    auto menuItem4 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 4", L"Icon", nullptr, true);
    auto menuItem3Children =
        winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    menuItem3Children.Append(*menuItem5);
    menuItem3Children.Append(*menuItem4);

    auto menuItem3 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 3", L"Icon", menuItem3Children);
    auto menuItem2Children =
        winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    menuItem2Children.Append(*menuItem3);

    auto menuItem2 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 2", L"Icon", menuItem2Children);
    auto menuItem1Children =
        winrt::single_threaded_observable_vector<HierarchicalNavigationViewDataBinding::Category>();
    menuItem1Children.Append(*menuItem2);

    auto menuItem1 =
        winrt::make_self<HierarchicalNavigationViewDataBinding::implementation::Category>
        (L"Menu item 1", L"Icon", menuItem1Children);

    m_categories.Append(*menuItem1);
    m_categories.Append(*menuItem6);
    m_categories.Append(*menuItem10);
}
...

階層型 NavigationView 内でのキーボード操作

ユーザーは、キーボードを使用して NavigationView の周囲にフォーカスを移動できます。 方向キーはペイン内の "内部ナビゲーション" を表示し、ツリー ビューでのアクションに従います。 キー アクションは、NavigationView 内を移動するとき、または HierarchicalNavigationView の Top および LeftCompact モードで表示されるポップアップ メニュー内を移動するときに変更されます。 階層型の NavigationView で各キーが実行できる特定のアクションを次に示します。

キー Left モード Top モード ポップアップ
[上へ] 現在フォーカスされている項目のすぐ上の項目にフォーカスを移動します。 何も実行しません。 現在フォーカスされている項目のすぐ上の項目にフォーカスを移動します。
[下へ] 現在フォーカスされている項目のすぐ下にフォーカスを移動します。* 何も実行しません。 現在フォーカスされている項目のすぐ下にフォーカスを移動します。*
権限 何も実行しません。 現在フォーカスされている項目の右隣の項目にフォーカスを移動します。 何も実行しません。
何も実行しません。 現在フォーカスされている項目の左隣の項目にフォーカスを移動します。 何も実行しません。
Space または Enter 項目に子がある場合、フォーカスを変更せずに項目を展開するか折りたたみます。 項目に子がある場合、子をポップアップとして展開し、ポップアップの最初の項目にフォーカスを置きます。 項目を呼び出すか選択して、ポップアップを閉じます。
Esc 何も実行しません。 何も実行しません。 ポップアップを閉じます。

Space または Enter キーでは常に項目の呼び出しまたは選択を行います。

\* 項目が視覚的に隣接している必要はありません。ペインの一覧の最後の項目にあるフォーカスは設定項目に移動します。

ウィンドウの背景

既定では、NavigationView ウィンドウでは表示モードに応じて次のようにさまざまな背景が使用されます。

  • ウィンドウは、コンテンツと横並びに左側に展開されると灰色の単色になります (Left モード)。
  • コンテンツの上部にオーバーレイとして開かれたウィンドウでは、アプリ内アクリルが使用されます (Top モード、Minimal モード、または Compact モード)。

ウィンドウの背景を変更するには、各モードで背景をレンダリングするのに使用される XAML テーマ リソースをオーバーライドします (各種表示モードに対してさまざまな背景をサポートするには、単一の PaneBackground プロパティではなくこの手法が使用されます)。

次の表に、各表示モードで使用されるテーマ リソースを示します。

表示モード テーマ リソース
NavigationViewExpandedPaneBackground
LeftCompact
LeftMinimal
NavigationViewDefaultPaneBackground
NavigationViewTopPaneBackground

この例では、App.xaml 内でテーマ リソースをオーバーライドする方法を示します。 テーマ リソースをオーバーライドする場合、最低でも "Default" および "HighContrast" のリソース辞書は常に指定し、"Light" または "Dark" リソース用の辞書は必要に応じて指定します。 詳細については、ResourceDictionary.ThemeDictionaries に関するページを参照してください。

重要

このコードでは、AcrylicBrush の WinUI 2 バージョンの使い方を示します。 プラットフォーム バージョンの AcrylicBrush を代わりに使用する場合、アプリ プロジェクトの最小バージョンは SDK 16299 以上である必要があります。 プラットフォーム バージョンを使用するには、muxm: へのすべての参照を削除します。

<Application ... xmlns:muxm="using:Microsoft.UI.Xaml.Media" ...>
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <ResourceDictionary>
                    <ResourceDictionary.ThemeDictionaries>
                        <ResourceDictionary x:Key="Default">
                            <!-- The "Default" theme dictionary is used unless a specific
                                 light, dark, or high contrast dictionary is provided. These
                                 resources should be tested with both the light and dark themes,
                                 and specific light or dark resources provided as needed. -->
                            <muxm:AcrylicBrush x:Key="NavigationViewDefaultPaneBackground"
                                   BackgroundSource="Backdrop"
                                   TintColor="LightSlateGray"
                                   TintOpacity=".6"/>
                            <muxm:AcrylicBrush x:Key="NavigationViewTopPaneBackground"
                                   BackgroundSource="Backdrop"
                                   TintColor="{ThemeResource SystemAccentColor}"
                                   TintOpacity=".6"/>
                            <LinearGradientBrush x:Key="NavigationViewExpandedPaneBackground"
                                     StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Color="LightSlateGray" Offset="0.0" />
                                <GradientStop Color="White" Offset="1.0" />
                            </LinearGradientBrush>
                        </ResourceDictionary>
                        <ResourceDictionary x:Key="HighContrast">
                            <!-- Always include a "HighContrast" dictionary when you override
                                 theme resources. This empty dictionary ensures that the
                                 default high contrast resources are used when the user
                                 turns on high contrast mode. -->
                        </ResourceDictionary>
                    </ResourceDictionary.ThemeDictionaries>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

先頭の空白

IsTitleBarAutoPaddingEnabled プロパティには、WinUI 2 2.2 以降が必要です。

一部のアプリでは、そのウィンドウのタイトル バーをカスタマイズするように選択できるため、そのアプリのコンテンツがタイトル バー領域に拡張される可能性があります。 NavigationView が、 ExtendViewIntoTitleBar API を使用してタイトル バーに拡張されるアプリ内のルート要素である場合、ドラッグ可能な領域との重なりを避けるためその対話型要素の位置が自動的に調整されます。

アプリのタイトル バーへの拡張

ドラッグ可能な領域が Window.SetTitleBar メソッドを呼び出すことによってアプリで指定されている場合、戻るボタンやメニュー ボタンをアプリ ウィンドウの上部近くに配置するには、IsTitleBarAutoPaddingEnabledfalse に設定します。

余白なしのアプリのタイトル バーへの拡張

<muxc:NavigationView x:Name="NavView" IsTitleBarAutoPaddingEnabled="False">

コメント

NavigationView のヘッダー領域の位置をさらに調整するには、Page リソース内などの NavigationViewHeaderMargin XAML テーマ リソースをオーバーライドします。

<Page.Resources>
    <Thickness x:Key="NavigationViewHeaderMargin">12,0</Thickness>
</Page.Resources>

このテーマ リソースによって、NavigationView.Header の周囲の余白が変更されます。