Bagikan melalui


Tampilan Navigasi

Kontrol NavigationView menyediakan navigasi tingkat atas untuk aplikasi Anda. Ini beradaptasi dengan berbagai ukuran layar dan mendukung gaya navigasi atas dan kiri .

navigasi atasnavigasi kiri
NavigationView mendukung panel atau menu navigasi atas dan kiri

Apakah ini kontrol yang tepat?

NavigationView adalah kontrol navigasi adaptif yang berfungsi dengan baik untuk:

  • Memberikan pengalaman navigasi yang konsisten di seluruh aplikasi Anda.
  • Mempertahankan real estat layar di jendela yang lebih kecil.
  • Mengatur akses ke banyak kategori navigasi.

Untuk pola navigasi lainnya, lihat Dasar-dasar desain navigasi.

UWP dan WinUI 2

Penting

Informasi dan contoh dalam artikel ini dioptimalkan untuk aplikasi yang menggunakan SDK Aplikasi Windows dan WinUI 3, tetapi umumnya berlaku untuk aplikasi UWP yang menggunakan WinUI 2. Lihat referensi API UWP untuk informasi dan contoh spesifik platform.

Bagian ini berisi informasi yang Anda butuhkan untuk menggunakan kontrol di aplikasi UWP atau WinUI 2.

Kontrol NavigationView untuk aplikasi UWP disertakan sebagai bagian dari WinUI 2. Untuk informasi selengkapnya, termasuk instruksi penginstalan, lihat WinUI 2. API untuk kontrol ini ada di namespace Windows.UI.Xaml.Controls dan Microsoft.UI.Xaml.Controls .

Sebaiknya gunakan WinUI 2 terbaru untuk mendapatkan gaya, templat, dan fitur terbaru untuk semua kontrol. Beberapa fitur NavigationView, seperti navigasi atas dan hierarkis , memerlukan Windows 10, versi 1809 (SDK 17763) atau yang lebih baru, atau WinUI 2.

Untuk menggunakan kode dalam artikel ini dengan WinUI 2, gunakan alias di XAML (kami menggunakan muxc) untuk mewakili API Pustaka Windows UI yang disertakan dalam proyek Anda. Lihat Mulai menggunakan WinUI 2 untuk informasi selengkapnya.

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

<muxc:NavigationView />

Membuat tampilan navigasi

Aplikasi Galeri WinUI 3 mencakup contoh interaktif dari sebagian besar kontrol, fitur, dan fungsi WinUI 3. Dapatkan aplikasi dari Microsoft Store atau dapatkan kode sumber di GitHub

Contoh ini menunjukkan cara membuat tampilan navigasi sederhana di 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>

Tampilkan mode

Anda dapat menggunakan properti PaneDisplayMode untuk mengonfigurasi gaya navigasi yang berbeda, atau mode tampilan, untuk NavigationView.

Atas

Panel diposisikan di atas konten.
PaneDisplayMode="Top"

Contoh navigasi atas

Kami merekomendasikan navigasi atas saat:

  • Anda memiliki 5 atau lebih sedikit kategori navigasi tingkat atas yang sama pentingnya, dan kategori navigasi tingkat atas tambahan yang berakhir di menu luapan dropdown dianggap kurang penting.
  • Anda perlu menampilkan semua opsi navigasi di layar.
  • Anda menginginkan lebih banyak ruang untuk konten aplikasi Anda.
  • Ikon tidak dapat menjelaskan kategori navigasi aplikasi Anda dengan jelas.

Left

Panel diperluas dan diposisikan di sebelah kiri konten.
PaneDisplayMode="Left"

Contoh panel navigasi kiri yang diperluas

Kami merekomendasikan navigasi kiri saat:

  • Anda memiliki 5-10 kategori navigasi tingkat atas yang sama pentingnya.
  • Anda ingin kategori navigasi sangat menonjol, dengan lebih sedikit ruang untuk konten aplikasi lainnya.

LeftCompact

Panel hanya memperlihatkan ikon hingga dibuka dan diposisikan di sebelah kiri konten. Saat dibuka, panel melapisi konten.
PaneDisplayMode="LeftCompact"

Contoh panel navigasi kiri yang ringkas

LeftMinimal

Hanya tombol menu yang ditampilkan hingga panel dibuka. Saat dibuka, panel melapisi sisi kiri konten.
PaneDisplayMode="LeftMinimal"

Contoh panel navigasi kiri minimal

Otomatis

Secara default, PaneDisplayMode diatur ke Auto. Dalam Auto mode, NavigationView beradaptasi antara LeftMinimal ketika jendela sempit, ke LeftCompact, dan kemudian Left saat jendela semakin lebar. Untuk informasi selengkapnya, lihat bagian perilaku adaptif.

Perilaku adaptif default navigasi kiri
Perilaku adaptif default NavigationView

anatomi

Gambar-gambar ini memperlihatkan tata letak panel, header, dan area konten kontrol saat dikonfigurasi untuk navigasi atas atau kiri .

Tata letak Tampilan Navigasi Atas
Tata letak navigasi atas

Tata letak Tampilan Navigasi Kiri
Tata letak navigasi kiri

Panel

Anda bisa menggunakan properti PaneDisplayMode untuk memposisikan panel di atas konten atau di sebelah kiri konten.

Panel NavigationView dapat berisi:

Panel kiri juga berisi:

  • Tombol menu untuk mengalihkan panel yang dibuka dan ditutup. Pada jendela aplikasi yang lebih besar saat panel terbuka, Anda dapat memilih untuk menyembunyikan tombol ini menggunakan properti IsPaneToggleButtonVisible .

NavigationView memiliki tombol kembali yang ditempatkan di sudut kiri atas panel. Namun, itu tidak secara otomatis menangani navigasi mundur dan menambahkan konten ke tumpukan belakang. Untuk mengaktifkan navigasi mundur, lihat bagian navigasi mundur.

Berikut adalah anatomi panel terperinci untuk posisi panel atas dan kiri.

Panel navigasi atas

Anatomi panel atas NavigationView

  1. Header
  2. Item navigasi
  3. Pemisah
  4. AutoSuggestBox (opsional)
  5. Tombol Pengaturan (opsional)

Panel navigasi kiri

Anatomi panel kiri NavigationView

  1. Tombol Menu
  2. Item navigasi
  3. Pemisah
  4. Header
  5. AutoSuggestBox (opsional)
  6. Tombol Pengaturan (opsional)

Anda bisa menggunakan FooterMenuItems untuk menempatkan item navigasi di akhir panel navigasi, berbeda dengan properti MenuItems yang menempatkan item di awal panel.

FooterMenuItems akan ditampilkan sebelum Settings item secara default. Item Settings masih dapat diubah menggunakan IsSettingsVisible properti .

Hanya item Navigasi yang harus ditempatkan di FooterMenuItems - konten lain yang perlu diratakan ke footer panel harus ditempatkan di PaneFooter.

Untuk contoh cara menambahkan FooterMenuItems ke NavigationView Anda, lihat kelas FooterMenuItems.

Gambar di bawah ini memperlihatkan NavigationView dengan item navigasi Akun, Kelir Anda, dan Bantuan di menu footer.

Tampilan Navigasi dengan FooterMenuItems

Anda bisa menempatkan konten bentuk bebas di footer panel dengan menambahkannya ke properti PaneFooter .

Navigasi atas footer panel
Footer panel atas

Navigasi kiri footer panel
Footer panel kiri

Judul dan header panel

Anda bisa menempatkan konten teks di area header panel dengan mengatur properti PaneTitle . Dibutuhkan string dan menampilkan teks di samping tombol menu.

Untuk menambahkan konten non-teks, seperti gambar atau logo, Anda bisa menempatkan elemen apa pun di header panel dengan menambahkannya ke properti PaneHeader .

Jika PanelTitle dan PaneHeader diatur, konten ditumpuk secara horizontal di samping tombol menu, dengan PanelTitle paling dekat dengan tombol menu.

Navigasi atas header panel
Header panel atas

Navigasi kiri header panel
Header panel kiri

Konten panel

Anda bisa menempatkan konten bentuk bebas di panel dengan menambahkannya ke properti PaneCustomContent .

Navigasi atas konten kustom panel
Konten kustom panel atas

Navigasi kiri konten kustom panel
Konten kustom panel kiri

Anda bisa menambahkan judul halaman dengan mengatur properti Header .

Contoh area header NavigationView
Header NavigationView

Area header diratakan secara vertikal dengan tombol navigasi di posisi panel kiri, dan terletak di bawah panel di posisi panel atas. Ini memiliki tinggi tetap 52 px. Tujuannya adalah untuk menahan judul halaman dari kategori navigasi yang dipilih. Header ditautkan ke bagian atas halaman dan bertindak sebagai titik kliping gulir untuk area konten.

Header terlihat kapan saja NavigationView berada dalam Minimal mode tampilan. Anda dapat memilih untuk menyembunyikan header dalam mode lain, yang digunakan pada lebar jendela yang lebih besar. Untuk menyembunyikan header, atur properti AlwaysShowHeader ke false.

Konten

Contoh area konten NavigationView
NavigasiTampilkan konten

Area konten adalah tempat sebagian besar informasi untuk kategori navigasi yang dipilih ditampilkan.

Kami merekomendasikan margin 12px untuk area konten Anda saat NavigationView dalam Minimal mode dan margin 24px sebaliknya.

Perilaku adaptif

Secara default, NavigationView secara otomatis mengubah mode tampilannya berdasarkan jumlah ruang layar yang tersedia untuknya. Properti CompactModeThresholdWidth dan ExpandedModeThresholdWidth menentukan titik henti di mana mode tampilan berubah. Anda dapat mengubah nilai-nilai ini untuk menyesuaikan perilaku mode tampilan adaptif.

Default

Saat PaneDisplayMode diatur ke nilai Autodefaultnya , perilaku adaptifnya adalah menampilkan:

  • Panel kiri yang diperluas pada lebar jendela besar (1008px atau lebih besar).
  • Panel navigasi kiri, khusus ikon (LeftCompact) pada lebar jendela sedang (641px hingga 1007px).
  • Hanya tombol menu (LeftMinimal) pada lebar jendela kecil (640px atau kurang).

Untuk informasi selengkapnya tentang ukuran jendela untuk perilaku adaptif, lihat Ukuran layar dan titik henti.

Perilaku adaptif default navigasi kiri
Perilaku adaptif default NavigationView

Minimal

Pola adaptif umum kedua adalah menggunakan panel kiri yang diperluas pada lebar jendela besar, dan hanya tombol menu pada lebar jendela sedang dan kecil.

Kami merekomendasikan ini ketika:

  • Anda menginginkan lebih banyak ruang untuk konten aplikasi pada lebar jendela yang lebih kecil.
  • Kategori navigasi Anda tidak dapat diwakili dengan jelas dengan ikon.

Navigasi kiri perilaku adaptif minimal
NavigasiLihat perilaku adaptif "minimal"

Untuk mengonfigurasi perilaku ini, atur CompactModeThresholdWidth ke lebar di mana Anda ingin panel diciutkan. Di sini, ini diubah dari default 640 menjadi 1007. Anda juga harus mengatur ExpandedModeThresholdWidth untuk memastikan nilai tidak bertentangan.

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

Ringkas

Pola adaptif umum ketiga adalah menggunakan panel kiri yang diperluas pada lebar jendela besar, dan panel navigasi LeftCompact, khusus ikon, pada lebar jendela sedang dan kecil.

Kami merekomendasikan ini ketika:

  • Penting untuk selalu menampilkan semua opsi navigasi di layar.
  • Kategori navigasi Anda dapat diwakili dengan jelas dengan ikon.

Perilaku adaptif ringkas navigasi kiri
Perilaku adaptif "ringkas" NavigationView

Untuk mengonfigurasi perilaku ini, atur CompactModeThresholdWidth ke 0.

<NavigationView CompactModeThresholdWidth="0"/>

Tidak ada perilaku adaptif

Untuk menonaktifkan perilaku adaptif otomatis, atur PaneDisplayMode ke nilai selain Auto. Di sini, diatur ke LeftMinimal, jadi hanya tombol menu yang ditampilkan terlepas dari lebar jendela.

Navigasi kiri tidak ada perilaku adaptif
Tampilan Navigasi dengan PaneDisplayMode diatur ke LeftMinimal

<NavigationView PaneDisplayMode="LeftMinimal" />

Seperti yang dijelaskan sebelumnya di bagian Mode tampilan, Anda dapat mengatur panel agar selalu berada di atas, selalu diperluas, selalu ringkas , atau selalu minimal. Anda juga dapat mengelola mode tampilan sendiri di kode aplikasi Anda. Contoh ini ditampilkan di bagian berikutnya.

Navigasi atas ke kiri

Saat Anda menggunakan navigasi atas di aplikasi, item navigasi akan diciutkan ke dalam menu luapan saat lebar jendela berkurang. Saat jendela aplikasi Anda sempit, ini dapat memberikan pengalaman pengguna yang lebih baik untuk mengalihkan PaneDisplayMode dari Top ke LeftMinimal navigasi, daripada membiarkan semua item diciutkan ke menu luapan.

Sebaiknya gunakan navigasi atas pada ukuran jendela besar dan navigasi kiri pada ukuran jendela kecil saat:

  • Anda memiliki sekumpulan kategori navigasi tingkat atas yang sama pentingnya untuk ditampilkan bersama-sama, sehingga jika satu kategori dalam set ini tidak pas di layar, Anda menciutkan ke navigasi kiri untuk memberi mereka kepentingan yang sama.
  • Anda ingin mempertahankan ruang konten sebanyak mungkin dalam ukuran jendela kecil.

Contoh ini menunjukkan cara menggunakan properti VisualStateManager dan AdaptiveTrigger.MinWindowWidth untuk beralih antara Top dan LeftMinimal navigasi.

Contoh perilaku adaptif atas atau kiri 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>

Tip

Saat Anda menggunakan AdaptiveTrigger.MinWindowWidth, status visual dipicu ketika jendela lebih lebar dari lebar minimum yang ditentukan. Ini berarti XAML default mendefinisikan jendela sempit, dan VisualState menentukan modifikasi yang diterapkan saat jendela semakin lebar. Panel defaultDisplayMode untuk NavigationView adalah Otomatis, jadi ketika lebar jendela kurang dari atau sama dengan CompactModeThresholdWidth, LeftMinimal navigasi digunakan. Ketika jendela semakin lebar, VisualState mengambil alih default, dan Top navigasi digunakan.

NavigationView tidak melakukan tugas navigasi apa pun secara otomatis. Saat pengguna mengetuk item navigasi, Tampilan Navigasi memperlihatkan item tersebut sebagai dipilih dan menaikkan peristiwa ItemInvoked . Jika ketukan menghasilkan item baru yang dipilih, peristiwa SelectionChanged juga dinaikkan.

Anda dapat menangani salah satu peristiwa untuk melakukan tugas yang terkait dengan navigasi yang diminta. Mana yang harus Anda tangani tergantung pada perilaku yang Anda inginkan untuk aplikasi Anda. Biasanya, Anda menavigasi ke halaman yang diminta dan memperbarui header NavigationView sebagai respons terhadap peristiwa ini.

  • ItemInvoked dinaikkan kapan saja pengguna mengetuk item navigasi, meskipun sudah dipilih. (Item juga dapat dipanggil dengan tindakan yang setara menggunakan mouse, keyboard, atau input lainnya. Untuk informasi selengkapnya, lihat Input dan interaksi.) Jika Anda menavigasi di handler ItemInvoked, secara default, halaman akan dimuat ulang, dan entri duplikat ditambahkan ke tumpukan navigasi. Jika Anda menavigasi saat item dipanggil, Anda harus melarang memuat ulang halaman, atau memastikan bahwa entri duplikat tidak dibuat di tumpukan belakang navigasi saat halaman dimuat ulang. (Lihat contoh kode.)
  • SelectionChanged dapat dinaikkan oleh pengguna yang memanggil item yang saat ini tidak dipilih, atau dengan mengubah item yang dipilih secara terprogram. Jika perubahan pilihan terjadi karena pengguna memanggil item, peristiwa ItemInvoked terjadi terlebih dahulu. Jika perubahan pilihan terprogram, ItemInvoked tidak dimunculkan.

Semua item navigasi adalah bagian dari model pilihan yang sama, apakah item tersebut merupakan bagian dari MenuItems atau FooterMenuItems. Hanya satu item navigasi yang dapat dipilih pada satu waktu.

Navigasi mundur

NavigationView memiliki tombol kembali bawaan; tetapi, seperti halnya navigasi penerusan, navigasi tidak melakukan navigasi mundur secara otomatis. Saat pengguna mengetuk tombol kembali, peristiwa BackRequested dinaikkan . Anda menangani kejadian ini untuk melakukan navigasi mundur. Untuk informasi selengkapnya dan contoh kode, lihat Riwayat navigasi dan navigasi mundur.

Dalam Minimal mode atau Compact , NavigationView Pane terbuka sebagai flyout. Dalam hal ini, mengklik tombol kembali akan menutup Pane dan menaikkan peristiwa PaneClosing sebagai gantinya.

Anda dapat menyembunyikan atau menonaktifkan tombol kembali dengan mengatur properti ini:

Tombol kembali NavigationView di panel navigasi kiri
Tombol kembali di panel navigasi kiri

Tombol kembali NavigationView di panel navigasi atas
Tombol kembali di panel navigasi atas

Contoh kode

Contoh ini memperlihatkan bagaimana Anda dapat menggunakan NavigationView dengan panel navigasi atas pada ukuran jendela besar dan panel navigasi kiri pada ukuran jendela kecil. Ini dapat disesuaikan dengan navigasi khusus kiri dengan menghapus pengaturan navigasi atas di VisualStateManager.

Contoh menunjukkan cara umum untuk menyiapkan data navigasi yang akan berfungsi untuk banyak skenario. Dalam contoh ini, Anda terlebih dahulu menyimpan (dalam tag NavigationViewItem) nama jenis lengkap halaman yang ingin Anda navigasikan. Di penanganan aktivitas, Anda membuka kotak nilai tersebut, mengubahnya menjadi objek Type(C#) atau Windows::UI::Xaml::Interop::TypeName(C++/WinRT), dan menggunakannya untuk menavigasi ke halaman tujuan. Ini memungkinkan Anda membuat pengujian unit untuk mengonfirmasi bahwa nilai di dalam tag Anda memiliki jenis yang valid. (Lihat juga Nilai tinju dan buka kotak ke IInspectable dengan C++/WinRT). Ini juga menunjukkan cara menerapkan navigasi mundur dengan tombol kembali NavigationView.

Kode ini mengasumsikan bahwa aplikasi Anda berisi halaman dengan nama berikut untuk menavigasi ke: HomePage, AppsPage, GamesPage, MusicPage, MyContentPage, dan SettingsPage. Kode untuk halaman ini tidak ditampilkan.

<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());
                        }
                    }
                }
            }
        }
    }
}

Navigasi hierarkis

Beberapa aplikasi mungkin memiliki struktur hierarkis yang lebih kompleks yang memerlukan lebih dari sekadar daftar datar item navigasi. Anda mungkin ingin menggunakan item navigasi tingkat atas untuk menampilkan kategori halaman, dengan item turunan yang menampilkan halaman tertentu. Ini juga berguna jika Anda memiliki halaman gaya hub yang hanya ditautkan ke halaman lain. Untuk kasus semacam ini, Anda harus membuat NavigationView hierarkis.

Untuk memperlihatkan daftar hierarkis item navigasi berlapis di panel, gunakan properti MenuItems atau properti MenuItemsSource dari NavigationViewItem. Setiap NavigationViewItem dapat berisi NavigationViewItems lainnya dan mengatur elemen seperti header item dan pemisah. Untuk memperlihatkan daftar hierarki saat menggunakan MenuItemsSource, atur ItemTemplate menjadi NavigationViewItem, dan ikat propertinya MenuItemsSource ke tingkat hierarki berikutnya.

Meskipun NavigationViewItem dapat berisi sejumlah tingkat berlapis, sebaiknya jaga hierarki navigasi aplikasi Anda tetap dangkal. Kami percaya dua tingkat sangat ideal untuk kegunaan dan pemahaman.

Tampilan Navigasi memperlihatkan hierarki dalam Topmode tampilan panel , Left, dan LeftCompact . Berikut adalah tampilan subtree yang diperluas di setiap mode tampilan panel:

NavigationView dengan Hierarki

Menambahkan hierarki item dalam markup

Contoh ini menunjukkan cara mendeklarasikan navigasi aplikasi hierarkis dalam markup 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>

Menambahkan hierarki item menggunakan pengikatan data

Menambahkan hierarki item menu ke NavigationView menurut

  • mengikat properti MenuItemsSource ke data hierarkis
  • menentukan templat item menjadi NavigationViewMenuItem, dengan Kontennya diatur menjadi label item menu, dan properti MenuItemsSource-nya terikat ke tingkat hierarki berikutnya

Contoh ini juga menunjukkan peristiwa Perluas dan Ciutkan . Peristiwa ini dinaikkan untuk item menu dengan anak-anak.

<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);
    }
}

Pilihan

Secara default, item apa pun dapat berisi turunan, dipanggil, atau dipilih.

Saat memberi pengguna pohon hierarkis opsi navigasi, Anda dapat memilih untuk membuat item induk tidak dapat dipilih, misalnya saat aplikasi Anda tidak memiliki halaman tujuan yang terkait dengan item induk tersebut. Jika item induk Anda dapat dipilih, disarankan Anda menggunakan mode tampilan panel Kiri-Diperluas atau Atas. Mode LeftCompact akan menyebabkan pengguna menavigasi ke item induk untuk membuka subtree anak setiap kali dipanggil.

Item yang dipilih akan menggambar indikator pilihannya di sepanjang tepi kirinya saat dalam mode kiri atau tepi bawahnya saat dalam mode atas. Ditunjukkan di bawah ini adalah NavigationViews dalam mode kiri dan atas tempat item induk dipilih.

NavigationView dalam mode kiri dengan induk dipilih

Tampilan Navigasi dalam mode atas dengan induk dipilih

Item terpilih mungkin tidak selalu terlihat. Jika anak dalam subtree yang diciutkan/tidak diperluas dipilih, leluhur pertama yang terlihat akan ditampilkan sebagai dipilih. Indikator pilihan akan berpindah kembali ke item terpilih jika/ketika sub-pohon diperluas.

Misalnya - pada gambar di atas, item Kalender dapat dipilih oleh pengguna, lalu pengguna dapat menciutkan subtreenya. Dalam hal ini, indikator pilihan akan muncul di bawah item Akun karena Akun adalah leluhur kalender pertama yang terlihat. Indikator pilihan akan berpindah kembali ke item Kalender saat pengguna memperluas subtree lagi.

Seluruh NavigationView akan menampilkan tidak lebih dari satu indikator pilihan.

Dalam mode Atas dan Kiri, mengklik panah pada NavigationViewItems akan memperluas atau menciutkan subtree. Mengklik atau mengetuk di tempat lain di NavigationViewItem akan memicu ItemInvoked peristiwa, dan juga akan menciutkan atau memperluas subtree.

Untuk mencegah item memperlihatkan indikator pilihan saat dipanggil, atur properti SelectsOnInvoked ke False, seperti yang ditunjukkan di bawah ini:

<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);
}
...

Keyboard dalam Tampilan Navigasi hierarkis

Pengguna dapat memindahkan fokus di sekitar NavigationView menggunakan keyboard mereka. Tombol panah mengekspos "navigasi dalam" di dalam panel dan mengikuti interaksi yang disediakan dalam tampilan pohon. Tindakan utama berubah saat menavigasi melalui NavigationView atau menu flyout-nya, yang ditampilkan dalam mode Ringkas Atas dan Kiri dari HierarchicalNavigationView. Di bawah ini adalah tindakan spesifik yang dapat dilakukan setiap kunci dalam Tampilan Navigasi hierarkis:

Tombol Dalam Mode Kiri Dalam Mode Atas Di Flyout
Naik Memindahkan fokus ke item tepat di atas item yang saat ini sedang dalam fokus. Tidak melakukan apa-apa. Memindahkan fokus ke item tepat di atas item yang saat ini sedang dalam fokus.
Tidak berfungsi Memindahkan fokus tepat di bawah item yang saat ini dalam fokus.* Tidak melakukan apa-apa. Memindahkan fokus tepat di bawah item yang saat ini dalam fokus.*
Right Tidak melakukan apa-apa. Memindahkan fokus ke item langsung ke kanan item yang saat ini sedang dalam fokus. Tidak melakukan apa-apa.
Left Tidak melakukan apa-apa. Memindahkan fokus ke item langsung ke kiri item yang saat ini sedang dalam fokus. Tidak melakukan apa-apa.
Spasi/Masukkan Jika item memiliki turunan, perluas/ciutkan item dan tidak mengubah fokus. Jika item memiliki anak, perluas turunan ke flyout dan fokus pada item pertama di flyout. Memanggil/memilih item dan menutup flyout.
Esc Tidak melakukan apa-apa. Tidak melakukan apa-apa. Menutup flyout.

Spasi atau masukkan kunci selalu memanggil/memilih item.

*Perhatikan bahwa item tidak perlu berdekatan secara visual, fokus akan berpindah dari item terakhir dalam daftar panel ke item pengaturan.

Latar Belakang Panel

Secara default, panel NavigationView menggunakan latar belakang yang berbeda tergantung pada mode tampilan:

  • panel adalah warna abu-abu solid saat diperluas di sebelah kiri, berdampingan dengan konten (dalam mode Kiri).
  • panel menggunakan akrilik dalam aplikasi saat terbuka sebagai overlay di atas konten (dalam mode Atas, Minimal, atau Ringkas).

Untuk mengubah latar belakang panel, Anda dapat mengambil alih sumber daya tema XAML yang digunakan untuk merender latar belakang di setiap mode. (Teknik ini digunakan daripada satu properti PaneBackground untuk mendukung latar belakang yang berbeda untuk mode tampilan yang berbeda.)

Tabel ini memperlihatkan sumber daya tema mana yang digunakan dalam setiap mode tampilan.

Mode tampilan Sumber daya tema
Left NavigationViewExpandedPaneBackground
LeftCompact
LeftMinimal
NavigationViewDefaultPaneBackground
Atas NavigationViewTopPaneBackground

Contoh ini menunjukkan cara mengambil alih sumber daya tema di App.xaml. Ketika Anda mengambil alih sumber daya tema, Anda harus selalu menyediakan kamus sumber daya "Default" dan "HighContrast" minimal, dan kamus untuk sumber daya "Terang" atau "Gelap" sesuai kebutuhan. Untuk informasi selengkapnya, lihat ResourceDictionary.ThemeDictionaries.

Penting

Kode ini menunjukkan cara menggunakan AcrylicBrush versi WinUI 2 . Jika Anda menggunakan versi platform AcrylicBrush sebagai gantinya, versi minimum untuk proyek aplikasi Anda harus SDK 16299 atau lebih besar. Untuk menggunakan versi platform, hapus semua referensi ke 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>

Spasi kosong atas

Properti IsTitleBarAutoPaddingEnabled ini memerlukan WinUI 2.2 atau yang lebih baru.

Beberapa aplikasi memilih untuk menyesuaikan bilah judul jendela mereka, berpotensi memperluas konten aplikasi mereka ke area bilah judul. Saat NavigationView adalah elemen akar dalam aplikasi yang meluas ke bilah judul menggunakan EXTENDViewIntoTitleBar API, kontrol secara otomatis menyesuaikan posisi elemen interaktifnya untuk mencegah tumpang tindih dengan wilayah yang dapat diseret.

Aplikasi yang diperluas ke bilah judul

Jika aplikasi Anda menentukan wilayah yang dapat diseret dengan memanggil metode Window.SetTitleBar dan Anda lebih suka tombol belakang dan menu mendekat ke bagian atas jendela aplikasi Anda, atur IsTitleBarAutoPaddingEnabled ke false.

Aplikasi meluas ke bilah judul tanpa padding tambahan

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

Keterangan

Untuk menyesuaikan lebih lanjut posisi area header NavigationView, ambil alih sumber daya tema NavigationViewHeaderMargin XAML, misalnya di sumber daya Halaman Anda.

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

Sumber daya tema ini memodifikasi margin di sekitar NavigationView.Header.