Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Kontrol NavigationView menyediakan navigasi tingkat atas untuk aplikasi Anda. Ini beradaptasi dengan berbagai ukuran layar dan mendukung gaya navigasi atas dan 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.
- Pada jendela yang lebih kecil, mempertahankan ruang layar.
- Mengatur akses ke banyak kategori navigasi.
Untuk pola navigasi lainnya, lihat Dasar-dasar desain navigasi.
Membuat tampilan navigasi
- API Penting:Kelas NavigationView
![]()
Aplikasi Galeri WinUI 3 mencakup contoh interaktif kontrol dan fitur WinUI. Dapatkan aplikasi dari Microsoft Store atau telusuri kode sumber pada 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>
Mode tampilan
Anda dapat menggunakan properti PaneDisplayMode untuk mengonfigurasi gaya navigasi yang berbeda, atau mode tampilan, untuk NavigationView.
Atas
Panel diposisikan di atas konten.PaneDisplayMode="Top"
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.
Kiri
Panel diperluas dan diposisikan di sebelah kiri konten.PaneDisplayMode="Left"
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"
KiriMinimal
Hanya tombol menu yang ditampilkan hingga panel dibuka. Saat dibuka, panel melapisi sisi kiri konten.PaneDisplayMode="LeftMinimal"
Contoh panel navigasi kiri minimal
Auto
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 bawaan dari NavigationView
Anatomi
Gambar-gambar ini memperlihatkan tata letak panel, header, dan area konten kontrol saat dikonfigurasi untuk navigasi atas atau kiri .
Tata letak navigasi atas
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:
- Objek NavigationViewItem . Item navigasi untuk menavigasi ke halaman tertentu.
- NavigationViewItemSeparator adalah objek. Pemisah untuk mengelompokkan item navigasi. Tetapkan properti Opacity ke 0 untuk merender pemisah sebagai spasi.
- Objek NavigationViewItemHeader . Header untuk pelabelan grup item.
- Kontrol AutoSuggestBox opsional untuk memungkinkan pencarian tingkat aplikasi. Tetapkan kontrol ke properti NavigationView.AutoSuggestBox .
- Titik masuk opsional untuk pengaturan aplikasi. Untuk menyembunyikan item pengaturan, atur properti IsSettingsVisible ke
false.
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
- Headers
- Elemen Navigasi
- Pemisah
- AutoSuggestBox (opsional)
- Tombol Pengaturan (opsional)
Panel navigasi sebelah kiri
- Tombol Menu
- Elemen Navigasi
- Pemisah
- Headers
- AutoSuggestBox (opsional)
- Tombol Pengaturan (opsional)
Elemen menu footer
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 properti IsSettingsVisible.
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 Akun, Keranjang Anda, dan Bantuan sebagai item navigasi di menu footer.
Pane kaki
Anda bisa menempatkan konten bentuk bebas di footer panel dengan menambahkannya ke properti PaneFooter .
Bagian bawah panel atas
Footer panel kiri
Judul dan kepala panel
Anda bisa menempatkan konten teks di area header panel dengan mengatur properti PaneTitle . Itu menerima 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.
Panel Header Atas
Header jendela kiri
Konten panel
Anda bisa menempatkan konten bentuk bebas di panel dengan menambahkannya ke properti PaneCustomContent .
Konten kustom bagian atas panel
Panel kiri dengan konten khusus
Header
Anda bisa menambahkan judul halaman dengan mengatur properti Header .
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.
Content
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.
Bawaan
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 bawaan dari NavigationView
Seminimal mungkin
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.
NavigasiLihat perilaku adaptif "minimal"
Untuk mengonfigurasi perilaku ini, atur CompactModeThresholdWidth ke lebar di mana Anda ingin panel menutup. Di sini, ini diubah dari default 640 menjadi 1007. Anda juga harus mengatur ExpandedModeThresholdWidth untuk memastikan nilai tidak bertentangan.
<NavigationView CompactModeThresholdWidth="1007" ExpandedModeThresholdWidth="1007"/>
Padat
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 NavigationView "compact"
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.
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 utama di aplikasi, item navigasi akan diciutkan ke dalam menu overflow saat lebar jendela berkurang. Saat jendela aplikasi Anda sempit, mengubah PaneDisplayMode dari Top ke LeftMinimal untuk navigasi dapat memberikan pengalaman pengguna yang lebih baik, daripada membiarkan semua item diciutkan ke menu melimpah.
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 secara bersama-sama, sehingga jika satu kategori dalam set ini tidak pas di layar, Anda beralih ke navigasi kiri untuk memberikan 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.
<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>
Petunjuk / Saran
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. ModeTampilanDefault untuk NavigationView adalah Auto, jadi ketika lebar jendela kurang dari atau sama dengan CompactModeThresholdWidth, navigasi LeftMinimal digunakan. Ketika jendela semakin lebar, VisualState mengambil alih default, dan Top navigasi digunakan.
Navigation
NavigationView tidak melakukan tugas navigasi apa pun secara otomatis. Saat pengguna mengetuk item navigasi, Tampilan Navigasi memperlihatkan item tersebut sebagai dipilih dan memicu peristiwa ItemInvoked. Jika ketukan menghasilkan item baru yang dipilih, event SelectionChanged juga dipicu.
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; namun, sama seperti navigasi maju, tombol ini tidak menjalankan navigasi mundur secara otomatis. Saat pengguna mengetuk tombol kembali, peristiwa BackRequested diaktifkan. Anda menangani peristiwa ini untuk melakukan navigasi ke belakang. Untuk informasi selengkapnya dan contoh kode, lihat Riwayat navigasi dan navigasi mundur.
Dalam modus Minimal 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:
-
IsBackButtonVisible: gunakan untuk menampilkan dan menyembunyikan tombol kembali. Properti ini mengambil nilai dari enumerasi NavigationViewBackButtonVisible, dan diatur menjadi
Autosecara default. Ketika tombol ditutup, tidak ada ruang yang disediakan untuk itu dalam tata letak. -
IsBackEnabled: gunakan untuk mengaktifkan atau menonaktifkan tombol kembali. Anda dapat mengikat properti ini ke properti CanGoBack dari bingkai navigasi Anda.
BackRequested tidak dinaikkan jika
IsBackEnabledadalahfalse.
Tombol kembali di panel navigasi kiri
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 Type(C#) atau Windows::UI::Xaml::Interop::TypeName(C++/WinRT), dan gunakan 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 Pembungkusan dan pembongkaran nilai ke IInspectable dengan C++/WinRT). Ini juga menunjukkan cara menerapkan navigasi mundur menggunakan tombol 'Kembali' dari 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=""/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Tag="NavigationViewDemo.GamesPage" Content="Games">
<NavigationViewItem.Icon>
<FontIcon Glyph=""/>
</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 elemen navigasi tingkat atas untuk menampilkan kategori halaman, dengan elemen bawahan yang menampilkan halaman tertentu. Ini juga bermanfaat jika Anda memiliki halaman bergaya hub yang hanya menautkan 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 NavigationViewItem lainnya dan menyusun 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:
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
Tambahkan hierarki item menu ke dalam NavigationView melalui
- melakukan pengikatan 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 mendemonstrasikan peristiwa Memperluas dan Menciutkan. 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 bawaan, item apa pun dapat berisi anak, 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 harus menavigasi ke item induk untuk membuka subtree anak setiap kali mode tersebut 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 mode atas di mana item induk dipilih.
Item terpilih mungkin tidak selalu terlihat. Jika elemen anak dalam subtree yang terlipat/tidak diperluas dipilih, leluhur pertama yang terlihat akan muncul sebagai yang 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 pertama Kalender 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 pada NavigationViewItem akan memicu event ItemInvoked, 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);
}
...
Penggunaan 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 berstruktur. 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:
| Key | Dalam Mode Kiri | Dalam Mode Puncak | Di Flyout |
|---|---|---|---|
| Ke atas | 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. |
| Ke bawah | 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.* |
| Benar | Tidak melakukan apa-apa. | Memindahkan fokus ke item yang secara langsung berada di kanan item yang saat ini dalam fokus. | Tidak melakukan apa-apa. |
| Kiri | Tidak melakukan apa-apa. | Memindahkan fokus ke item yang berada tepat di sebelah kiri item yang sedang difokuskan. | Tidak melakukan apa-apa. |
| Spasi/Masukkan | Jika item memiliki anak elemen, memperluas/menciutkan 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. |
Tombol spasi atau tombol enter selalu mengaktifkan/memilih item.
*Perhatikan bahwa item tidak perlu berdekatan secara visual, fokus akan berpindah dari item terakhir dalam daftar panel ke item pengaturan.
Kustomisasi NavigationView
Latar Belakang Panel
Secara default, panel NavigationView menggunakan latar belakang yang berbeda tergantung pada mode tampilan:
- Panel berwarna abu-abu solid saat diperluas di sebelah kiri, berdampingan dengan konten (dalam mode Kiri).
- panel menggunakan efek akrilik dalam aplikasi saat terbuka sebagai lapisan di atas konten dalam mode Atas, Minimal, dan 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 |
|---|---|
| Kiri | Latar Belakang Panel Diperluas Tampilan Navigasi |
| LeftCompact KiriMinimal |
Latar Belakang Pane Bawaan NavigationView |
| Atas | LatarBelakangPanelAtasTampilanNavigasi |
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.
Spasi kosong atas
Aplikasi yang menyesuaikan bilah judul jendela mereka sering memperluas konten ke area bilah judul. Saat NavigationView digunakan bersama bilah judul kustom, Anda perlu memastikan elemen interaktifnya (tombol kembali, tombol panel) tidak tumpang tindih dengan wilayah seret bilah judul.
Menggunakan kontrol TitleBar (disarankan)
Pendekatan yang disarankan adalah menempatkan kontrol Bilah Judul di atas NavigationView, dan membiarkan Bilah Judul menangani tombol kembali dan tombol panel. Ini adalah pola yang digunakan oleh aplikasi WinUI 3 Gallery.
Karena kontrol Bilah Judul memiliki tombol kembali dan tombol pengalih panel, Anda harus menyembunyikan versi bawaan NavigationView dengan mengatur IsBackButtonVisible="Collapsed" dan IsPaneToggleButtonVisible="False". TitleBar kemudian meneruskan interaksi tersebut ke NavigationView melalui penanganan aktivitas:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TitleBar x:Name="titleBar"
Title="My App"
IsPaneToggleButtonVisible="True"
PaneToggleRequested="TitleBar_PaneToggleRequested"
IsBackButtonVisible="{x:Bind contentFrame.CanGoBack, Mode=OneWay}"
BackRequested="TitleBar_BackRequested" />
<NavigationView x:Name="NavView"
Grid.Row="1"
IsBackButtonVisible="Collapsed"
IsPaneToggleButtonVisible="False"
DisplayModeChanged="NavView_DisplayModeChanged">
<Frame x:Name="contentFrame" />
</NavigationView>
</Grid>
Di code-behind Anda, perluas konten ke bilah judul, tetapkan kontrol TitleBar, dan hubungkan penanganan peristiwa untuk menghubungkan tombol TitleBar ke NavigationView.
this.ExtendsContentIntoTitleBar = true;
this.SetTitleBar(titleBar);
// Toggle the NavigationView pane open or closed when the TitleBar button is clicked.
private void TitleBar_PaneToggleRequested(TitleBar sender, object args)
{
NavView.IsPaneOpen = !NavView.IsPaneOpen;
}
// Navigate back when the TitleBar back button is clicked.
private void TitleBar_BackRequested(TitleBar sender, object args)
{
if (contentFrame.CanGoBack)
{
contentFrame.GoBack();
}
}
// Hide the pane toggle button in the TitleBar when NavigationView switches to Top mode,
// since the pane isn't applicable in that layout.
private void NavView_DisplayModeChanged(NavigationView sender,
NavigationViewDisplayModeChangedEventArgs args)
{
titleBar.IsPaneToggleButtonVisible =
sender.PaneDisplayMode != NavigationViewPaneDisplayMode.Top;
}
Dengan pola ini, kontrol Bilah Judul mengelola wilayah seret dan tombol interaktif, sehingga NavigationView tidak memerlukan padding otomatis.
Menggunakan elemen bilah judul kustom
Jika Anda menentukan wilayah seret kustom menggunakan Window.SetTitleBar dengan UIElement Anda sendiri alih-alih kontrol TitleBar, NavigationView secara otomatis menambahkan padding untuk mencegah elemen interaktifnya tumpang tindih dengan area bilah judul.
Jika Anda lebih suka tombol kembali dan menu untuk mendekat ke bagian atas jendela aplikasi Anda, atur IsTitleBarAutoPaddingEnabled ke false:
<NavigationView x:Name="NavView" IsTitleBarAutoPaddingEnabled="False">
Menyesuaikan margin header
Untuk menyesuaikan posisi area header NavigationView lebih lanjut, ambil alih sumber daya tema NavigationViewHeaderMargin XAML 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.
Topik terkait
Windows developer