Condividi tramite


Vista di Navigazione

Il controllo NavigationView fornisce uno spostamento di primo livello per la tua app. Si adatta a un'ampia gamma di dimensioni dello schermo e supporta sia gli stili di spostamento superiore che sinistro .

navigazione superiore navigazione sinistra
NavigationView supporta sia il pannello di navigazione superiore che quello sinistro o il menu

Questo è il controllo giusto?

NavigationView è un controllo di spostamento adattivo ideale per:

  • Fornire un'esperienza di spostamento coerente in tutta l'app.
  • Risparmiare spazio sullo schermo delle finestre più piccole.
  • Organizzare l'accesso a numerose categorie di spostamento.

Per altri pattern di navigazione, vedere Nozioni di base sul design di navigazione.

Creare una visualizzazione di navigazione

L'app Raccolta WinUI 3 include esempi interattivi della maggior parte dei controlli e delle funzionalità di WinUI 3. Scaricare l'app da Microsoft Store od ottenere il codice sorgente su GitHub

Questo esempio mostra come creare di una visualizzazione di navigazione semplice in 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>

Modalità di visualizzazione

Puoi usare la proprietà PaneDisplayMode per configurare differenti stili di spostamento o modalità di visualizzazione, per NavigationView.

In alto

Il riquadro è posizionato sopra il contenuto.
PaneDisplayMode="Top"

Esempio di navigazione superiore

È consigliabile spostarsi in alto quando:

  • Hai al massimo 5 categorie di spostamento di primo livello ugualmente importanti e ogni ulteriore categoria di spostamento di primo livello che viene inserita nel menu extra a discesa è considerata meno importante.
  • Devi visualizzare tutte le opzioni di spostamento sullo schermo.
  • Vuoi più spazio per il contenuto dell'app.
  • Le icone non possono descrivere in modo chiaro le categorie di spostamento dell'app.

Sinistra

Il riquadro è espanso e posizionato a sinistra del contenuto.
PaneDisplayMode="Left"

Esempio di riquadro di spostamento a sinistra espanso

È consigliabile spostarsi a sinistra quando:

  • Hai 5-10 categorie di spostamento di primo livello altrettanto importanti.
  • Vuoi che le categorie di spostamento siano molto importanti, riservando meno spazio all'altro contenuto dell'app.

SinistraCompatto

Il riquadro mostra solo le icone fino a quando non viene aperto e posizionato a sinistra del contenuto. Quando viene aperto, il riquadro sovrappone il contenuto.
PaneDisplayMode="LeftCompact"

Esempio di riquadro di spostamento a sinistra compatto

LeftMinimal

Viene visualizzato solo il pulsante del menu finché il riquadro non viene aperto. Quando si apre, il riquadro si sovrappone al lato sinistro del contenuto.
PaneDisplayMode="LeftMinimal"

Esempio di riquadro di spostamento a sinistra minimo

Auto

Per impostazione predefinita, PaneDisplayMode è impostata su Auto. In Auto modalità, NavigationView si adatta tra LeftMinimal quando la finestra è stretta, a LeftCompact e quindi Left quando la finestra diventa più ampia. Per altre info, vedi la sezione comportamento adattivo .

Comportamento adattivo predefinito dello spostamento a sinistra
Comportamento adattivo predefinito di NavigationView

Anatomia

Queste immagini mostrano il layout delle aree del riquadro, dell'intestazione e del contenuto del controllo quando sono configurate per lo spostamento in alto o a sinistra .

Layout di navigazione principale
Layout di navigazione superiore

Layout Di NavigationView a sinistra
Layout di navigazione a sinistra

Riquadro

Puoi usare la proprietà PaneDisplayMode per posizionare il riquadro sopra o a sinistra del contenuto.

Il riquadro NavigationView può contenere:

Il riquadro a sinistra contiene anche:

  • Un pulsante di menu per alternare il riquadro aperto e chiuso. Nelle finestre delle app più grandi quando il riquadro è aperto, è possibile scegliere di nascondere questo pulsante usando la proprietà IsPaneToggleButtonVisible .

NavigationView include un pulsante Indietro posizionato nell'angolo in alto a sinistra del riquadro. Tuttavia, non gestisce automaticamente lo spostamento indietro e non aggiunge il contenuto allo stack Indietro. Per abilitare lo spostamento indietro, vedere la sezione navigazione all'indietro .

Ecco l'anatomia del riquadro dettagliata per le posizioni del riquadro superiore e a sinistra.

Riquadro di spostamento superiore

Anatomia del riquadro superiore di NavigationView

  1. Headers
  2. Elementi di spostamento
  3. Separatori
  4. AutoSuggestBox (facoltativo)
  5. Pulsante delle impostazioni (facoltativo)

Riquadro di spostamento sinistro

Anatomia del riquadro sinistro di NavigationView

  1. Pulsante Menu
  2. Elementi di spostamento
  3. Separatori
  4. Headers
  5. AutoSuggestBox (facoltativo)
  6. Pulsante delle impostazioni (facoltativo)

È possibile utilizzare FooterMenuItems per posizionare gli elementi di spostamento alla fine del riquadro di spostamento, a differenza della proprietà MenuItems che inserisce gli elementi all'inizio del riquadro.

Per impostazione predefinita, FooterMenuItems verrà visualizzato prima dell'elemento Settings. L'elemento Settings può comunque essere attivato o disattivato usando la proprietà IsSettingsVisible.

Solo gli elementi di navigazione devono essere inseriti in FooterMenuItems. Tutti gli altri contenuti che devono essere allineati al piè di pagina del riquadro devono essere posizionati in PaneFooter.

Per un esempio di come aggiungere FooterMenuItems al controllo NavigationView, vedere la classe FooterMenuItems.

L'immagine seguente mostra un controllo NavigationView con Account, Carrello e Guida nel menu a piè di pagina.

Una NavigationView con elementi del menu piè di pagina

È possibile inserire contenuto in formato libero nel piè di pagina del riquadro aggiungendolo alla proprietà PaneFooter .

Navigazione superiore del piè di pagina del riquadro
piè di pagina del riquadro superiore

Nav a sinistra del piè di pagina del pannello
Piè di pagina del riquadro laterale sinistro

Intestazione e titolo del riquadro

È possibile inserire il contenuto di testo nell'area dell'intestazione del riquadro impostando la proprietà PaneTitle . Accetta una stringa e mostra il testo accanto al pulsante di menu.

Per aggiungere contenuto non di testo, ad esempio un'immagine o un logo, è possibile inserire qualsiasi elemento nell'intestazione del riquadro aggiungendolo alla proprietà PaneHeader .

Se sono impostati sia PaneTitle che PaneHeader, il contenuto viene impilato orizzontalmente accanto al pulsante di menu, con PaneTitle più vicino al pulsante di menu.

Spostamento superiore dell'intestazione del riquadro
Intestazione del riquadro superiore

Intestazione del riquadro, navigazione a sinistra
Intestazione del riquadro sinistro

Contenuto del riquadro

È possibile inserire contenuto in formato libero nel riquadro aggiungendolo alla proprietà PaneCustomContent .

Barra di navigazione superiore del contenuto personalizzato
Contenuto personalizzato del riquadro superiore

Riquadro di spostamento a sinistra del contenuto personalizzato
Contenuto personalizzato del pannello sinistro

È possibile aggiungere un titolo di pagina impostando la proprietà Header .

Esempio dell'area dell'intestazione di NavigationView
Intestazione di "NavigationView"

L'area dell'intestazione è allineata verticalmente con il pulsante di spostamento nella posizione del riquadro sinistro e si trova sotto il riquadro nella posizione del riquadro superiore. Ha un'altezza fissa pari a 52 pixel. La sua finalità è di contenere il titolo della pagina della categoria di navigazione selezionata. L'intestazione è ancorata alla parte superiore della pagina e funge da punto di ritaglio dello scorrimento per l'area del contenuto.

L'intestazione è visibile ogni volta che NavigationView si trova in modalità Minimal. Puoi scegliere di nascondere l'intestazione nelle altre modalità utilizzate con larghezze di finestra più ampie. Per nascondere l'intestazione, impostare la proprietà AlwaysShowHeader su .

Content

Esempio di area di contenuto di NavigationView
Contenuto di NavigationView

L'area del contenuto è il punto in cui è visualizzata gran parte delle informazioni sulla categoria di navigazione selezionata.

Consigliamo margini di 12 pixel per l'area del contenuto, quando NavigationView è in modalità Minimal e 24 pixel negli altri casi.

Comportamento adattivo

Per impostazione predefinita, NavigationView modifica automaticamente la propria modalità di visualizzazione sulla base dello spazio sullo schermo che ha a disposizione. Le proprietà CompactModeThresholdWidth e ExpandedModeThresholdWidth specificano i punti di interruzione in cui cambia la modalità di visualizzazione. Puoi modificare questi valori per personalizzare il comportamento adattivo della modalità di visualizzazione.

Impostazione predefinita

Quando PaneDisplayMode è impostato sul valore predefinito Auto, il comportamento adattivo consiste nel mostrare:

  • Un riquadro a sinistra espanso sulle larghezze di finestre grandi (1008 pixel o superiore).
  • Un riquadro di spostamento a sinistra (LeftCompact), solo a icona, su larghezze di finestre medie (da 641 a 1007 pixel).
  • Solo un pulsante di menu (LeftMinimal) su larghezze di finestre piccole (fino a 640 pixel).

Per altre informazioni sulle dimensioni delle finestre per il comportamento adattivo, vedere Dimensioni dello schermo e punti di interruzione.

Comportamento adattivo predefinito dello spostamento a sinistra
Comportamento adattivo predefinito di NavigationView

Minime

Un secondo modello adattivo comune consiste nell'utilizzare un riquadro a sinistra espanso su larghezze di finestre grandi e solo un pulsante di menu su larghezze di finestre piccole e medie.

Ti consigliamo questo approccio quando:

  • Vuoi più spazio per il contenuto dell'app su larghezze di finestre piccole.
  • Le categorie di spostamento non possono essere rappresentate in modo chiaro con icone.

Comportamento adattivo minimo per lo spostamento a sinistra
Comportamento adattivo "minimo" di NavigationView

Per configurare questo comportamento, imposta CompactModeThresholdWidth sulla larghezza in corrispondenza della quale desideri che il riquadro venga compresso. In questo caso viene cambiato dal valore predefinito 640 a 1007. Devi anche impostare ExpandedModeThresholdWidth per assicurare che i valori non siano in conflitto.

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

Compatto

Un terzo modello adattivo comune è quello di utilizzare un riquadro a sinistra espanso su larghezze di finestre grandi e un riquadro di spostamento LeftCompact, solo a icona, su larghezze di finestre piccole e medie.

Ti consigliamo questo approccio quando:

  • È importante visualizzare sempre tutte le opzioni di spostamento sullo schermo.
  • Le categorie di spostamento possono essere rappresentate in modo chiaro con icone.

Comportamento adattivo compatto dello spostamento a sinistra
Comportamento adattivo "compact" di NavigationView

Per configurare questo comportamento, imposta CompactModeThresholdWidth su 0.

<NavigationView CompactModeThresholdWidth="0"/>

Nessun comportamento adattivo

Per disabilitare il comportamento adattivo automatico, imposta PaneDisplayMode su un valore diverso da Auto. Qui è impostato su LeftMinimal, quindi viene mostrato solo il pulsante di menu indipendentemente dalla larghezza della finestra.

Spostamento a sinistra senza comportamento adattivo
NavigationView con PaneDisplayMode impostato su LeftMinimal

<NavigationView PaneDisplayMode="LeftMinimal" />

Come descritto in precedenza nella sezione modalità di visualizzazione , è possibile impostare il riquadro in modo che sia sempre in alto, sempre espanso, sempre compatto o sempre minimo. Puoi anche gestire autonomamente le modalità di visualizzazione nel codice dell'app. Un esempio è illustrato nella sezione successiva.

Spostamento da superiore a sinistra

Quando si utilizza lo spostamento superiore nell'app, gli elementi di spostamento si comprimono in un menu extra al diminuire della larghezza della finestra. Quando la finestra dell'app è stretta, puoi migliorare l'esperienza utente passando PaneDisplayMode da Top a LeftMinimal, anziché lasciare che tutte le voci vengano compresse nel menu extra.

Ti consigliamo di utilizzare lo spostamento superiore nelle dimensioni di finestre grandi e lo spostamento a sinistra nelle dimensioni di finestre piccole:

  • Hai un gruppo di categorie di spostamento di primo livello altrettanto importanti da visualizzare insieme, in modo tale che se una categoria di questo gruppo non si adatta allo schermo, esegui la compressione passando allo spostamento a sinistra per attribuire la stessa importanza.
  • Vuoi mantenere quanto più spazio possibile per il contenuto nelle finestre piccole.

Questo esempio illustra come usare una proprietà VisualStateManager e AdaptiveTrigger.MinWindowWidth per passare da una navigazione all'altra TopLeftMinimal .

Esempio di comportamento adattivo superiore o a sinistra 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>

Suggerimento

Quando utilizzi AdaptiveTrigger.MinWindowWidth, lo stato di visualizzazione si attiva quando la finestra è più ampia della larghezza minima specificata. In altri termini, il valore predefinito XAML definisce la finestra stretta e VisualState definisce le modifiche applicate quando la finestra diventa più ampia. Il valore predefinito di PaneDisplayMode per la visualizzazione di spostamento è Auto; pertanto quando la larghezza della finestra è minore o uguale a CompactModeThresholdWidth, viene usato lo spostamento LeftMinimal. Quando la finestra diventa più ampia, VisualState sostituisce il valore predefinito e viene utilizzato lo spostamento Top.

NavigationView non esegue automaticamente alcuna attività di navigazione. Quando l'utente tocca un elemento di spostamento, NavigationView mostra l'elemento come selezionato e genera un evento ItemInvoked . Se il tocco comporta la selezione di un nuovo elemento, viene generato anche un evento SelectionChanged .

Puoi gestire entrambi gli eventi per eseguire attività relative allo spostamento richiesto. La scelta di quale gestire dipende dal comportamento che desideri per la tua app. In genere, passi alla pagina richiesta e aggiorni l'intestazione della NavigationView in risposta a questi eventi.

  • ItemInvoked viene generato ogni volta che l'utente tocca un elemento di spostamento, anche se è già selezionato. L'elemento può anche essere richiamato con un'azione equivalente usando mouse, tastiera o altro input. Per altre info, vedi Input e interazioni. Se si passa al gestore ItemInvoked, per impostazione predefinita, la pagina verrà ricaricata e viene aggiunta una voce duplicata allo stack di navigazione. Se navighi quando viene richiamato un elemento, devi impedire il ricaricamento della pagina o assicurarti che una voce duplicata non venga creata nel backstack di spostamento quando la pagina viene ricaricata. (Vedi gli esempi di codice).
  • SelectionChanged può essere generato da un utente che richiama un elemento attualmente non selezionato o modificando l'elemento selezionato a livello di codice. Se la modifica della selezione avviene perché un utente ha richiamato un elemento, l'evento ItemInvoked si verifica per primo. Se la modifica della selezione è a livello di codice, ItemInvoked non viene attivato.

Tutti gli elementi di spostamento fanno parte dello stesso modello di selezione, indipendentemente dal fatto che facciano parte di MenuItems o FooterMenuItems. È possibile selezionare un solo elemento di navigazione alla volta.

Spostamento indietro

NavigationView include un pulsante Indietro, ma, come per lo spostamento avanti, non esegue automaticamente lo spostamento indietro. Quando l'utente tocca il pulsante Indietro, viene generato l'evento BackRequested . Puoi gestire questo evento per eseguire lo spostamento indietro. Per altre info ed esempi di codice, vedi Cronologia di spostamento e spostamento indietro.

In Minimal modalità or Compact , NavigationView Pane è aperto come riquadro a comparsa. In questo caso, invece facendo clic sul pulsante Indietro Pane verrà chiuso e verrà generato l'evento PaneClosing.

Puoi nascondere o disabilitare il pulsante Indietro impostando queste proprietà:

  • IsBackButtonVisible: consente di visualizzare e nascondere il pulsante Indietro. Questa proprietà assume un valore dell'enumerazione NavigationViewBackButtonVisible ed è impostata su Auto per impostazione predefinita. Quando il pulsante è compresso, non viene riservato alcuno spazio nel layout.
  • IsBackEnabled: usare per abilitare o disabilitare il pulsante Indietro. È possibile associare questa proprietà alla proprietà CanGoBack del frame di navigazione. BackRequested non viene generato se IsBackEnabled è false.

Pulsante Indietro di NavigationView nel riquadro di navigazione a sinistra
Pulsante Indietro nella barra di navigazione a sinistra

Pulsante Indietro di NavigationView nella parte superiore del riquadro di spostamento
Pulsante Indietro nella barra di navigazione superiore

Esempio di codice

Questo esempio mostra come è possibile utilizzare NavigationView sia con un riquadro di spostamento superiore su finestre grandi che con un riquadro di spostamento a sinistra su finestre piccole. Può essere adattato alla navigazione solo a sinistra rimuovendo le impostazioni di navigazione in alto nel VisualStateManager.

L'esempio mostra un modo comune per impostare i dati di spostamento che funzionano per molti scenari. In questo esempio, si archivia prima (nel tag di NavigationViewItem) il nome completo della pagina a cui si desidera spostarsi. Nel gestore eventi, estrarre quel valore, trasformarlo in un oggetto Type (C#) o Windows::UI::Xaml::Interop::TypeName (C++/WinRT) e usarlo per navigare alla pagina di destinazione. In questo modo è possibile creare unit test per verificare che i valori all'interno dei tag siano di un tipo valido. Vedere anche Boxing e unboxing di valori in IInspectable con C++/WinRT. Mostra anche come implementare lo spostamento indietro con il pulsante Indietro di NavigationView.

Questo codice presuppone che l'app contenga pagine con i nomi seguenti per passare a: HomePage, AppsPage, GamesPage, MusicPage, MyContentPage e SettingsPage. Il codice per queste pagine non è mostrato.

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

Navigazione gerarchica

Alcune app possono avere una struttura gerarchica più complessa che richiede più di un semplice elenco di elementi di spostamento. Può essere opportuno usare elementi di spostamento di primo livello per visualizzare categorie di pagine ed elementi figlio per visualizzare pagine specifiche. Una struttura di questo tipo è utile anche se sono presenti pagine di tipo hub che si collegano solo ad altre pagine. Per questi casi, è necessario creare un controllo NavigationView di tipo gerarchico.

Per visualizzare un elenco gerarchico di elementi di spostamento annidati nel riquadro, utilizzare la proprietà MenuItems o la proprietà MenuItemsSource di NavigationViewItem. Ogni NavigationViewItem può contenere altri NavigationViewItem ed elementi di carattere organizzativo come le intestazioni e i separatori di elementi. Per visualizzare un elenco gerarchico quando usi MenuItemsSource, imposta ItemTemplate come NavigationViewItem e associa la relativa proprietà MenuItemsSource al livello successivo della gerarchia.

Anche se NavigationViewItem può contenere un numero qualsiasi di livelli annidati, è consigliabile limitare la profondità della gerarchia di spostamento dell'app. Una gerarchia a due livelli è la soluzione ideale per assicurare usabilità e comprensione.

NavigationView mostra le modalità di visualizzazione della gerarchia e TopLeftLeftCompact del riquadro. Di seguito è illustrato l'aspetto di un sottoalbero espanso in ognuna delle modalità di visualizzazione del riquadro:

NavigationView con gerarchia

Aggiunta di una gerarchia di elementi nel markup

Questo esempio mostra come dichiarare lo spostamento gerarchico delle app nel 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>

Aggiunta di una gerarchia di elementi tramite data binding

Puoi aggiungere una gerarchia di voci di menu a NavigationView nei modi seguenti:

  • Associando la proprietà MenuItemsSource ai dati gerarchici
  • Definendo il modello di elemento come NavigationViewMenuItem, con il relativo contenuto impostato come etichetta della voce di menu e la relativa proprietà MenuItemsSource associata al livello successivo della gerarchia

In questo esempio vengono illustrati anche gli eventi Expanding e Collapsed . Questi eventi vengono generati per una voce di menu con elementi figlio.

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

Selection

Per impostazione predefinita, qualsiasi elemento può contenere elementi figlio, essere richiamato o selezionato.

Quando si fornisce agli utenti una struttura gerarchica di opzioni di spostamento, è possibile scegliere di rendere non selezionabili gli elementi padre, ad esempio quando nell'app non è associata una pagina di destinazione a tali elementi. Se gli elementi padre sono selezionabili, è consigliabile usare le modalità di visualizzazione Left-Expanded o Riquadro superiore. In modalità LeftCompact l'utente deve passare all'elemento padre per aprire il sottoalbero figlio ogni volta che viene richiamato.

Gli indicatori di selezione degli elementi vengono visualizzati lungo il bordo sinistro quando il riquadro è in modalità Left o lungo il bordo inferiore quando invece è in modalità Top. Di seguito sono riportati esempi di NavigationView in modalità Left e Top con un elemento padre selezionato.

NavigationView in modalità sinistra con elemento padre selezionato

NavigationView in modalità superiore con l'elemento principale selezionato

È possibile che non sempre l'elemento selezionato rimanga visibile. Se è selezionato un elemento figlio in un sottoalbero compresso o non espanso, verrà visualizzato come selezionato il primo predecessore visibile. L'indicatore di selezione verrà spostato di nuovo sull'elemento selezionato se/quando il sottoalbero verrà espanso.

Nell'immagine precedente, ad esempio, l'utente potrebbe selezionare l'elemento del calendario e quindi comprimere il relativo sottoalbero. In questo caso, l'indicatore di selezione verrebbe visualizzato sotto l'elemento Account poiché Account è il primo predecessore visibile del calendario. L'indicatore di selezione passerà di nuovo all'elemento del calendario quando l'utente espanderà il sottoalbero.

L'intero controllo NavigationView visualizzerà un solo indicatore di selezione.

In entrambe le modalità Top e Left, quando fai clic sulle frecce di NavigationViewItem, il sottoalbero viene espanso o compresso. Se si fa clic o si tocca altrove in NavigationViewItem, l'evento ItemInvoked verrà attivato e verrà compresso o espanso anche il sottoalbero.

Per impedire a un elemento di visualizzare l'indicatore di selezione quando viene richiamato, impostarne la proprietà SelectsOnInvoked su False, come illustrato di seguito:

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

Utilizzo dei tasti nel controllo NavigationView di tipo gerarchico

Gli utenti possono spostare lo stato attivo nel NavigationView usando la tastiera . I tasti freccia attivano la "navigazione interna" all'interno del riquadro e ne seguono le interazioni come definite nella visualizzazione ad albero . Le azioni dei tasti cambiano quando ti sposti nella struttura di NavigationView o nel relativo menu a comparsa, che viene visualizzato nelle modalità Top e LeftCompact di HierarchicalNavigationView. Di seguito sono riportate le azioni specifiche che ogni tasto può eseguire in un controllo NavigationView di tipo gerarchico:

Key In modalità Left In modalità Top Nel riquadro a comparsa
Attivo Sposta lo stato attivo sull'elemento immediatamente superiore a quello con stato attivo. Non esegue operazioni. Sposta lo stato attivo sull'elemento immediatamente superiore a quello con stato attivo.
Giù Sposta lo stato attivo sull'elemento immediatamente inferiore a quello con stato attivo.* Non esegue operazioni. Sposta lo stato attivo sull'elemento immediatamente inferiore a quello con stato attivo.*
Giusto Non esegue operazioni. Sposta lo stato attivo sull'elemento immediatamente a destra di quello con stato attivo. Non esegue operazioni.
Sinistra Non esegue operazioni. Sposta lo stato attivo sull'elemento immediatamente a sinistra di quello con stato attivo. Non esegue operazioni.
BARRA SPAZIATRICE/INVIO Se sono presenti elementi figlio, espande o comprime l'elemento e non cambia lo stato attivo. Se sono presenti elementi figlio, espande gli elementi figlio in un riquadro a comparsa e posiziona lo stato attivo sul primo elemento nel riquadro. Richiama o seleziona l'elemento e chiude il riquadro a comparsa.
Esc Non esegue operazioni. Non esegue operazioni. Chiude il riquadro a comparsa.

La BARRA SPAZIATRICE o il tasto INVIO richiama sempre o seleziona un elemento.

*Non è necessario che gli elementi siano visivamente adiacenti. Lo stato attivo passa dall'ultimo elemento nell'elenco del riquadro all'elemento delle impostazioni.

Sfondi del riquadro

Per impostazione predefinita, il riquadro NavigationView usa uno sfondo diverso a seconda della modalità di visualizzazione:

  • il riquadro è di colore grigio uniforme quando viene espanso a sinistra, fianco a fianco con il contenuto (in modalità Left).
  • il riquadro utilizza l'acrilico in-app quando è aperto come sovrimpressione sul contenuto (in modalità superiore, minima o compatta).

Per modificare lo sfondo del riquadro, puoi sovrascrivere le risorse del tema XAML usate per eseguire il rendering dello sfondo in ogni modalità. Questa tecnica viene usata al posto di una singola proprietà PaneBackground per supportare sfondi diversi per modalità di visualizzazione differenti.

Questa tabella mostra quale risorsa del tema viene utilizzata in ogni modalità di visualizzazione.

Modalità di visualizzazione Risorsa del tema
Sinistra SfondoRiquadroEspansoVistaNavigazione
SinistraCompatto
LeftMinimal
SfondoPannelloPredefinitoVistaNavigazione
In alto SfondoPannelloSuperioreNavigazione

Questo esempio mostra come sovrascrivere le risorse del tema in App.xaml. Quando sostituisci le risorse del tema, dovresti sempre fornire almeno i dizionari delle risorse "Default" e "HighContrast" e i dizionari per le risorse "Light" o "Dark" secondo le necessità. Per altre info, vedi ResourceDictionary.ThemeDictionaries.

Importante

Questo codice illustra come usare la versione WinUI 2 di AcrylicBrush. Se invece usi la versione della piattaforma di AcrylicBrush, la versione minima per il tuo progetto app deve essere SDK 16299 o successiva. Per usare la versione della piattaforma, rimuovi tutti i riferimenti a 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>

Spazi vuoti superiori

La IsTitleBarAutoPaddingEnabled proprietà richiede WinUI 2.2 o versione successiva.

Alcune app scelgono di personalizzare la barra del titolo della finestra, estendendo potenzialmente il contenuto dell'app nell'area della barra del titolo. Quando NavigationView è l'elemento radice nelle app che si estendono nella barra del titolo usando l'API ExtendViewIntoTitleBar, il controllo regola automaticamente la posizione dei relativi elementi interattivi per evitare sovrapposizioni con l'area trascinabile.

Un'app che si estende nella barra del titolo

Se l'app specifica l'area trascinabile chiamando il metodo Window.SetTitleBar e si preferisce che i pulsanti indietro e menu si avvicinino alla parte superiore della finestra dell'app, impostare IsTitleBarAutoPaddingEnabled su false.

Estensione dell'app nella barra del titolo senza spaziatura interna aggiuntiva

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

Osservazioni:

Per regolare ulteriormente la posizione dell'area di intestazione di NavigationView, eseguire l'override della risorsa del tema XAML NavigationViewHeaderMargin , ad esempio nelle risorse della pagina.

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

Questa risorsa del tema modifica il margine intorno a NavigationView.Header.

UWP e WinUI 2

Importante

Le informazioni e gli esempi in questo articolo sono ottimizzati per le app che usano Windows App SDK e WinUI 3, ma sono generalmente applicabili alle app UWP che usano WinUI 2. Per informazioni ed esempi specifici della piattaforma, consultare le indicazioni di riferimento sulle API UWP.

Questa sezione contiene informazioni necessarie per usare il controllo in un'app UWP o WinUI 2.

Il controllo NavigationView per le app UWP è incluso come parte della di WinUI 2. Per maggiori informazioni, incluse le istruzioni per l'installazione, vedere WinUI 2. Le API per questo controllo esistono negli spazi dei nomi Windows.UI.Xaml.Controls e Microsoft.UI.Xaml.Controls .

È consigliabile usare la versione più recente di WinUI 2 per ottenere gli stili, i modelli e le funzionalità più recenti per tutti i controlli. Alcune funzionalità di NavigationView, ad esempio la navigazione superiore e gerarchica , richiedono Windows 10, versione 1809 (SDK 17763) o versioni successive o WinUI 2.

Per usare il codice in questo articolo con WinUI 2, usa un alias in XAML (usiamo muxc) per rappresentare le API della libreria dell'interfaccia utente di Windows incluse nel progetto. Per altre informazioni, vedi Introduzione a WinUI 2 .

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

<muxc:NavigationView />