Partilhar via


Vista de Navegação

O controle NavigationView fornece navegação de nível superior para seu aplicativo. Adapta-se a uma variedade de tamanhos de ecrã e suporta estilos de navegação superior e à esquerda .

navegação superior navegação esquerda
NavigationView suporta tanto o painel de navegação superior quanto o esquerdo ou o menu

Será este o controlo correto?

O NavigationView é um controlo de navegação adaptável que funciona bem para:

  • Fornecer uma experiência de navegação consistente em todo o seu aplicativo.
  • Preservar o espaço de exibição em janelas menores.
  • Organizar o acesso a muitas categorias de navegação.

Para outros padrões de navegação, consulte Noções básicas de design de navegação.

Criar uma vista de navegação

O aplicativo WinUI 3 Gallery inclui exemplos interativos da maioria dos controles, recursos e funcionalidades do WinUI 3. Obtenha o aplicativo no da Microsoft Store ou obtenha o código-fonte em do GitHub

Este exemplo mostra como criar um modo de exibição de navegação simples em 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>

Modos de exibição

Você pode usar a propriedade PaneDisplayMode para configurar diferentes estilos de navegação, ou modos de exibição, para o NavigationView.

Início

O painel está posicionado acima do conteúdo.
PaneDisplayMode="Top"

Exemplo de navegação superior

Recomendamos a navegação superior quando:

  • Você tem 5 ou menos categorias de navegação de nível superior que são igualmente importantes, e quaisquer categorias de navegação de nível superior adicionais que acabam no menu de excesso são consideradas menos importantes.
  • Você precisa mostrar todas as opções de navegação na tela.
  • Você quer mais espaço para o conteúdo do seu aplicativo.
  • Os ícones não podem descrever claramente as categorias de navegação do seu aplicativo.

Esquerda

O painel é expandido e posicionado à esquerda do conteúdo.
PaneDisplayMode="Left"

Exemplo de painel de navegação esquerdo expandido

Recomendamos a navegação à esquerda quando:

  • Você tem de 5 a 10 categorias de navegação de nível superior igualmente importantes.
  • Você quer que as categorias de navegação sejam muito proeminentes, com menos espaço para outros conteúdos do aplicativo.

LeftCompact

O painel mostra apenas ícones até ser aberto e está posicionado à esquerda do conteúdo. Quando aberto, o painel sobrepõe o conteúdo.
PaneDisplayMode="LeftCompact"

Exemplo de painel de navegação esquerdo compacto

EsquerdaMínimo

Apenas o botão de menu é mostrado até que o painel seja aberto. Quando aberto, o painel sobrepõe o lado esquerdo do conteúdo.
PaneDisplayMode="LeftMinimal"

Exemplo do painel de navegação esquerdo mínimo

Auto

Por padrão, PaneDisplayMode é definido como Auto. No Auto modo, o NavigationView adapta-se entre LeftMinimal quando a janela é estreita, para LeftCompacte depois Left à medida que a janela fica mais larga. Para obter mais informações, consulte a secção comportamento adaptável.

Comportamento adaptativo padrão de navegação à esquerda
Comportamento adaptável padrão do NavigationView

Anatomia

Essas imagens mostram o layout do painel, do cabeçalho e das áreas de conteúdo do controlo quando configurado para navegação superior ou navegação esquerda .

Layout de Top NavigationView
Layout de navegação superior

NavigationView layout esquerdo
Layout de navegação à esquerda

Painel

Você pode usar a propriedade PaneDisplayMode para posicionar o painel acima do conteúdo ou à esquerda do conteúdo.

O painel NavigationView pode conter:

  • NavigationViewItem objetos. Itens de navegação para navegar para páginas específicas.
  • NavigationViewItemSeparator objetos. Separadores para agrupar itens de navegação. Defina a propriedade Opacity como 0 para renderizar o separador como espaço.
  • NavigationViewItemHeader objetos. Cabeçalhos para rotular grupos de itens.
  • Um controlo opcional AutoSuggestBox para permitir a pesquisa ao nível da aplicação. Atribua o controlo à propriedade NavigationView.AutoSuggestBox.
  • Um ponto de entrada opcional para as configurações da aplicação . Para ocultar o item de configurações, defina a propriedade IsSettingsVisible como .

O painel esquerdo também contém:

  • Um botão de menu para alternar o painel aberto e fechado. Em janelas de aplicativos maiores quando o painel estiver aberto, você pode optar por ocultar esse botão usando a propriedade IsPaneToggleButtonVisible .

O NavigationView tem um botão Voltar que é colocado no canto superior esquerdo do painel. No entanto, ele não manipula automaticamente a navegação para trás e adiciona conteúdo à pilha de trás. Para habilitar a navegação para trás, consulte a seção de navegação para trás .

Aqui está a anatomia detalhada do painel para as posições superior e à esquerda.

Painel de navegação superior

Anatomia do painel superior do NavigationView

  1. Headers
  2. Itens de navegação
  3. Separadores
  4. AutoSuggestBox (opcional)
  5. Botão Configurações (opcional)

Painel de navegação esquerdo

Anatomia do painel esquerdo do NavigationView

  1. Botão Menu
  2. Itens de navegação
  3. Separadores
  4. Headers
  5. AutoSuggestBox (opcional)
  6. Botão Configurações (opcional)

Você pode usar FooterMenuItems para colocar itens de navegação no final do painel de navegação, em contraste com a propriedade MenuItems que coloca itens no início do painel.

FooterMenuItems será exibido antes do Settings item por padrão. O item Settings ainda pode ser ativado/desativado usando a propriedade IsSettingsVisible.

Somente os itens de navegação devem ser colocados em FooterMenuItems - qualquer outro conteúdo que precise ser alinhado ao rodapé do painel deve ser colocado em PaneFooter.

Para obter um exemplo de como adicionar FooterMenuItems ao seu NavigationView, consulte a classe FooterMenuItems.

A imagem abaixo mostra um NavigationView com Conta, o Seu Carrinhoe Ajuda como itens de navegação no menu de rodapé.

uma Visualização de Navegação com Itens de Menu de Rodapé

Você pode colocar conteúdo de forma livre no rodapé do painel, adicionando-o à propriedade PaneFooter marcada como .

topo de navegação do rodapé do painel
Rodapé do painel superior

Rodapé da navegação do painel esquerdo
Rodapé do painel esquerdo

Título do painel e cabeçalho

Você pode colocar conteúdo de texto na área do cabeçalho do painel definindo a propriedade PaneTitle . Ele usa uma cadeia de caracteres e mostra o texto ao lado do botão de menu.

Para adicionar conteúdo não textual, como uma imagem ou logotipo, você pode colocar qualquer elemento no cabeçalho do painel adicionando-o à propriedade PaneHeader .

Se PaneTitle e PaneHeader estiverem definidos, o conteúdo será empilhado horizontalmente ao lado do botão de menu, com o PaneTitle mais próximo do botão de menu.

nav de topo do cabeçalho do painel
Cabeçalho do painel superior

Cabeçalho do painel de navegação esquerdo
Cabeçalho do painel esquerdo

Conteúdo do painel

Você pode colocar conteúdo de forma livre no painel adicionando-o à propriedade PaneCustomContent.

Conteúdo personalizado do painel no topo da navegação
Conteúdo personalizado do painel superior

Conteúdo personalizado de navegação no painel esquerdo
Conteúdo personalizado do painel esquerdo

Você pode adicionar um título de página definindo a propriedade Header .

Exemplo de área de cabeçalho NavigationView
cabeçalho de NavigationView

A área do cabeçalho está alinhada verticalmente com o botão de navegação na posição do painel à esquerda e encontra-se abaixo do botão na posição do painel superior. Tem uma altura fixa de 52 px. Seu objetivo é manter o título da página da categoria de navegação selecionada. O cabeçalho é fixado na parte superior da página e atua como um ponto de corte de rolagem para a área de conteúdo.

O cabeçalho fica visível sempre que o NavigationView está no Minimal modo de exibição. Você pode optar por ocultar o cabeçalho em outros modos, que são usados em larguras de janela maiores. Para ocultar o cabeçalho, defina a propriedade AlwaysShowHeader como false.

Content

Exemplo de da área de conteúdo NavigationView
conteúdo do NavigationView

A área de conteúdo é onde a maioria das informações para a categoria de navegação selecionada é exibida.

Recomendamos margens de 12 px para sua área de conteúdo quando o NavigationView estiver no Minimal modo e margens de 24 px caso contrário.

Comportamento adaptativo

Por padrão, o NavigationView altera automaticamente seu modo de exibição com base na quantidade de espaço na tela disponível. As propriedades CompactModeThresholdWidth e ExpandedModeThresholdWidth especificam os pontos de interrupção nos quais o modo de exibição é alterado. Você pode modificar esses valores para personalizar o comportamento do modo de exibição adaptável.

Predefinido

Quando PaneDisplayMode é definido como seu valor padrão de Auto, o comportamento adaptável deve mostrar:

  • Um painel esquerdo expandido em grandes larguras de janela (1008px ou superior).
  • Um painel de navegação esquerdo, apenas com ícones (LeftCompact) em larguras médias de janela (641px a 1007px).
  • Apenas um botão de menu (LeftMinimal) em pequenas larguras de janela (640px ou menos).

Para obter mais informações sobre tamanhos de janela para comportamento adaptável, consulte Tamanhos de tela e pontos de interrupção.

Comportamento adaptativo padrão de navegação à esquerda
Comportamento adaptável padrão do NavigationView

Mínimo

Um segundo padrão adaptável comum é usar um painel esquerdo expandido em grandes larguras de janela e apenas um botão de menu em larguras de janela médias e pequenas.

Recomendamos isso quando:

  • Você quer mais espaço para o conteúdo do aplicativo em larguras de janela menores.
  • As suas categorias de navegação não podem ser claramente representadas com ícones.

Navegação à esquerda com comportamento adaptativo mínimo
de comportamento adaptativo "mínimo" do NavigationView

Para configurar esse comportamento, defina CompactModeThresholdWidth para a largura na qual você deseja que o painel seja recolhido. Aqui, o valor foi alterado do padrão de 640 para 1007. Você também deve definir ExpandedModeThresholdWidth para garantir que os valores não entrem em conflito.

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

Compacto

Um terceiro padrão adaptável comum é usar um painel esquerdo expandido em grandes larguras de janela e um painel de navegação LeftCompact, somente com ícones, em larguras de janela médias e pequenas.

Recomendamos isso quando:

  • É importante mostrar sempre todas as opções de navegação no ecrã.
  • As suas categorias de navegação podem ser claramente representadas com ícones.

Comportamento adaptativo compacto da navegação à esquerda
Comportamento adaptativo "compacto" do NavigationView

Para configurar esse comportamento, defina CompactModeThresholdWidth como 0.

<NavigationView CompactModeThresholdWidth="0"/>

Sem comportamento adaptativo

Para desativar o comportamento adaptável automático, defina PaneDisplayMode como um valor diferente de Auto. Aqui, ele é definido como LeftMinimal, portanto, apenas o botão de menu é mostrado, independentemente da largura da janela.

Navegação à esquerda sem comportamento adaptativo
NavigationView com ModoDeExibiçãoDoPainel definido como EsquerdaMinima

<NavigationView PaneDisplayMode="LeftMinimal" />

Conforme descrito anteriormente na seção Modos de exibição , você pode definir o painel para estar sempre no topo, sempre expandido, sempre compacto ou sempre mínimo. Você também pode gerenciar os modos de exibição sozinho no código do aplicativo. Um exemplo disso é mostrado na próxima seção.

Navegação de cima para a esquerda

Quando se utiliza a navegação superior na sua aplicação, os itens de navegação são recolhidos num menu de excedente à medida que a largura da janela diminui. Quando a janela da sua aplicação é estreita, pode proporcionar uma melhor experiência ao utilizador alternar o PaneDisplayMode de Top para navegação LeftMinimal, em vez de permitir que todos os itens colapsem no menu suspenso.

Recomendamos o uso da navegação superior em janelas grandes e a navegação à esquerda em janelas pequenas quando:

  • Você tem um conjunto de categorias de navegação de nível superior igualmente importantes para serem exibidas juntas, de modo que, se uma categoria desse conjunto não couber na tela, você ajusta para uma navegação lateral à esquerda para dar a elas a mesma importância.
  • Você deseja preservar o máximo de espaço de conteúdo possível em janelas pequenas.

Este exemplo mostra como usar o VisualStateManager e a propriedade AdaptiveTrigger.MinWindowWidth para alternar entre navegação Top e LeftMinimal.

Exemplo de comportamento adaptativo superior ou esquerdo 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>

Sugestão

Quando você usa AdaptiveTrigger.MinWindowWidth, o estado visual é acionado quando a janela é maior do que a largura mínima especificada. Isso significa que o XAML padrão define a janela estreita e o VisualState define as modificações que são aplicadas quando a janela fica mais ampla. O PaneDisplayMode padrão para o NavigationView é Auto, portanto, quando a largura da janela é menor ou igual a CompactModeThresholdWidth, a navegação LeftMinimal é usada. Quando a janela fica maior, o VisualState sobrepõe o padrão e é utilizada a navegação Top.

O NavigationView não executa nenhuma tarefa de navegação automaticamente. Quando o usuário toca em um item de navegação, o NavigationView mostra esse item como selecionado e gera um evento ItemInvoked . Se o toque resultar na seleção de um novo item, um evento SelectionChanged também será gerado.

Você pode manipular qualquer evento para executar tarefas relacionadas à navegação solicitada. Qual deles você deve lidar depende do comportamento que você deseja para seu aplicativo. Normalmente, você navega até a página solicitada e atualiza o cabeçalho NavigationView em resposta a esses eventos.

  • ItemInvoked é acionado sempre que o utilizador toca num item de navegação, mesmo que este já esteja selecionado. (O item também pode ser invocado com uma ação equivalente usando mouse, teclado ou outra entrada. Para saber mais, veja Entrada e interações.) Se você navegar no manipulador ItemInvoked, por padrão, a página será recarregada e uma entrada duplicada será adicionada à pilha de navegação. Se navegares quando um item for invocado, deves impedir o recarregamento da página, ou então assegurar que uma entrada duplicada não seja criada na pilha de navegação quando a página for recarregada. (Veja exemplos de código.)
  • SelectionChanged pode ser gerado por um usuário invocando um item que não está selecionado no momento ou alterando programaticamente o item selecionado. Se a alteração de seleção ocorrer porque um usuário invocou um item, o evento ItemInvoked ocorrerá primeiro. Se a alteração de seleção for programática, ItemInvoked não será gerado.

Todos os itens de navegação fazem parte do mesmo modelo de seleção, quer façam parte de MenuItems ou de FooterMenuItems. Apenas um item de navegação pode ser selecionado de cada vez.

Navegação para trás

O NavigationView tem um botão Voltar incorporado; mas, tal como acontece com a navegação para a frente, não executa automaticamente a navegação para trás. Quando o utilizador toca no botão voltar, o evento BackRequested é acionado. Você manipula esse evento para executar a navegação inversa. Para obter mais informações e exemplos de código, consulte Histórico de navegação e navegação retroativa.

No modo Minimal ou Compact, o NavigationView Pane é aberto como um menu deslizante. Nesse caso, clicar no botão Voltar fechará o Pane e aumentará o evento PaneClosing em vez disso.

Você pode ocultar ou desativar o botão Voltar definindo estas propriedades:

  • IsBackButtonVisible: use para mostrar e ocultar o botão voltar. Essa propriedade usa um valor da enumeração NavigationViewBackButtonVisible e é definida como Auto por padrão. Quando o botão é recolhido, não é reservado nenhum espaço para ele no esquema.
  • IsBackEnabled: utilizar para ativar ou desativar o botão voltar. Você pode vincular essa propriedade à propriedade CanGoBack do quadro de navegação. BackRequested não é gerado se IsBackEnabled estiver false.

botão de retroceder do NavigationView no painel de navegação à esquerda
O botão Voltar no painel de navegação esquerdo

botão de retroceder do NavigationView no painel de navegação superior
O botão Voltar no painel de navegação superior

Exemplo de código

Este exemplo mostra como você pode usar NavigationView com um painel de navegação superior em tamanhos de janela grandes e um painel de navegação esquerdo em tamanhos de janela pequenos. Ele pode ser adaptado à navegação somente à esquerda removendo as configurações de navegação superior no VisualStateManager.

O exemplo demonstra uma maneira comum de configurar dados de navegação que funcionarão para muitos cenários. Neste exemplo, você primeiro armazena (na tag do NavigationViewItem) o nome completo do tipo da página para a qual deseja navegar. No manipulador de eventos, você descompacta esse valor, transforma-o em um objeto Type(C#) ou Windows::UI::Xaml::Interop::TypeName(C++/WinRT) e usa-o para navegar até a página de destino. Isso permite que você crie testes de unidade para confirmar se os valores dentro de suas tags são de um tipo válido. (Consulte também Valores de Boxe e unboxing para IInspectable com C++/WinRT). Ele também demonstra como implementar a navegação para trás com o botão Voltar do NavigationView.

Esse código pressupõe que seu aplicativo contenha páginas com os seguintes nomes para navegar: HomePage, AppsPage, GamesPage, MusicPage, MyContentPage e SettingsPage. O código para estas páginas não é mostrado.

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

Navegação hierárquica

Alguns aplicativos podem ter uma estrutura hierárquica mais complexa que requer mais do que apenas uma lista simples de itens de navegação. Você pode querer usar itens de navegação de nível superior para exibir categorias de páginas, com subitens exibindo páginas específicas. Também é útil se você tiver páginas no estilo hub que apenas vinculam a outras páginas. Para esses tipos de casos, você deve criar um NavigationView hierárquico.

Utilize a propriedade MenuItems ou a propriedade MenuItemsSource de NavigationViewItempara mostrar uma lista hierárquica de itens de navegação aninhados no painel. Cada NavigationViewItem pode conter outros NavigationViewItems e elementos de organização, como cabeçalhos e separadores de itens. Para mostrar uma lista hierárquica ao usar MenuItemsSource, defina o ItemTemplate como NavigationViewItem e vincule a propriedade MenuItemsSource ao próximo nível da hierarquia.

Embora o NavigationViewItem possa conter qualquer número de níveis aninhados, recomendamos manter a hierarquia de navegação da sua aplicação pouco profunda. Acreditamos que dois níveis é ideal para usabilidade e compreensão.

NavigationView mostra a hierarquia nos modos de exibição de painel Top, Left e LeftCompact. Veja a aparência de uma subárvore expandida em cada um dos modos de exibição do painel:

NavigationView com Hierarquia

Adicionando uma hierarquia de itens na marcação

Este exemplo mostra como declarar a navegação hierárquica do aplicativo na marcação 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>

Adicionando uma hierarquia de itens usando a vinculação de dados

Adicionar uma hierarquia de itens de menu ao NavigationView por

  • vinculando a propriedade MenuItemsSource aos dados hierárquicos
  • definindo o modelo de item como um NavigationViewMenuItem, com seu Content definido como o rótulo do item de menu e sua propriedade MenuItemsSource vinculada ao próximo nível da hierarquia

Este exemplo também demonstra os eventos Expanding e Collapsed. Estes eventos são criados para um item de menu com crianças.

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

Seleção

Por padrão, qualquer item pode conter filhos, ser invocado ou ser selecionado.

Ao fornecer aos usuários uma árvore hierárquica de opções de navegação, você pode optar por tornar os itens pai não selecionáveis, por exemplo, quando seu aplicativo não tem uma página de destino associada a esse item pai. Se os itens pai estiverem selecionáveis, é recomendável usar os modos de exibição Left-Expanded ou Painel superior. O modo LeftCompact fará com que o utilizador navegue até o item pai para abrir a subárvore filha sempre que for invocada.

Os itens selecionados desenharão seus indicadores de seleção ao longo da borda esquerda quando estiverem no modo esquerdo ou da borda inferior quando estiverem no modo superior. Abaixo são apresentadas as NavigationViews nos modos esquerdo e superior, onde um item pai está selecionado.

NavigationView no modo esquerdo com o pai selecionado

NavigationView em modo de topo com o pai selecionado

O item selecionado pode nem sempre permanecer visível. Se um filho em uma subárvore recolhida/não expandida for selecionado, seu primeiro ancestral visível será mostrado como selecionado. O indicador de seleção voltará para o item selecionado se/quando a subárvore for expandida.

Por exemplo - na imagem acima, o item Calendário pode ser selecionado pelo usuário e, em seguida, o usuário pode recolher sua subárvore. Nesse caso, o indicador de seleção apareceria abaixo do item Conta, pois Conta é o primeiro ancestral visível do Calendário. O indicador de seleção voltará para o item Calendário à medida que o usuário expande a subárvore novamente.

Todo o NavigationView mostrará apenas um indicador de seleção.

Nos modos Superior e Esquerdo, clicar nas setas em NavigationViewItems expandirá ou recolherá a subárvore. Clicar ou tocar outro no NavigationViewItem acionará o evento ItemInvoked e também recolherá ou expandirá a subárvore.

Para impedir que um item mostre o indicador de seleção quando invocado, defina sua propriedade SelectsOnInvoked como False, conforme mostrado abaixo:

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

Uso do teclado dentro de um NavigationView hierárquico

Os usuários podem mover o foco ao redor do NavigationView usando o teclado. As teclas de seta ativam a "navegação interna" no painel e seguem as interações especificadas na visualização em árvore . As principais ações mudam ao navegar no NavigationView ou no seu menu suspenso, que é exibido nos modos Top e Left-compact do HierarchicalNavigationView. Abaixo estão as ações específicas que cada tecla pode executar em um NavigationView hierárquico:

Key Em Modo Esquerdo No modo superior No menu flutuante
Up Move o foco para o item diretamente acima do item atualmente em foco. Não faz nada. Move o foco para o item diretamente acima do item atualmente em foco.
Baixo Move o foco diretamente abaixo do item atualmente em foco.* Não faz nada. Move o foco diretamente abaixo do item atualmente em foco.*
Certo Não faz nada. Move o foco para o item diretamente à direita do item atualmente em foco. Não faz nada.
Esquerda Não faz nada. Mova o foco para o item diretamente à esquerda do item que está atualmente em foco. Não faz nada.
Espaço/Enter Se o item tiver filhos, expande/recolhe o item e não muda o foco. Se o item tiver filhos, expande os filhos em um submenu e coloca o foco no primeiro item no submenu. Invoca/seleciona item e fecha o menu suspenso.
Esc Não faz nada. Não faz nada. Fecha o menu suspenso.

A chave de espaço ou enter sempre invoca/seleciona um item.

*Observe que os itens não precisam estar visualmente adjacentes, o foco será movido do último item na lista do painel para o item de configurações.

Fundos do painel

Por padrão, o painel NavigationView usa um plano de fundo diferente, dependendo do modo de exibição:

  • o painel é de uma cor cinza sólida quando expandido para a esquerda, paralelamente ao conteúdo (no modo Esquerdo).
  • o painel usa acrílico dentro da aplicação quando aberto como uma sobreposição sobre o conteúdo (em modo Topo, Mínimo ou Compacto).

Para modificar o plano de fundo do painel, você pode substituir os recursos de tema XAML usados para renderizar o plano de fundo em cada modo. (Essa técnica é usada em vez de uma única propriedade PaneBackground para oferecer suporte a diferentes planos de fundo para diferentes modos de exibição.)

Esta tabela mostra qual recurso de tema é usado em cada modo de exibição.

Modo de exibição Recurso temático
Esquerda FundoDoPainelExpandidoDaNavegação
LeftCompact
EsquerdaMínimo
FundoPredefinidoDoPainelDeNavegação
Início FundoPainelSuperiorVistaNavegação

Este exemplo mostra como substituir os recursos de tema em App.xaml. Ao substituir recursos temáticos, deve-se sempre fornecer dicionários de recursos "Padrão" e "Alto Contraste" no mínimo, e dicionários para recursos "Claro" ou "Escuro", conforme necessário. Para obter mais informações, consulte ResourceDictionary.ThemeDictionaries.

Importante

Este código mostra como usar a versão WinUI 2 do AcrylicBrush. Se você usar a versão de plataforma do AcrylicBrush em vez disso, a versão mínima para seu projeto de aplicativo deve ser SDK 16299 ou superior. Para usar a versão da plataforma, remova todas as referências ao 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>

Espaço em branco superior

A IsTitleBarAutoPaddingEnabled propriedade requer WinUI 2.2 ou posterior.

Algumas aplicações optam por personalizar a barra de título da janela, estendendo potencialmente o conteúdo da aplicação para a área da barra de título. Quando NavigationView é o elemento raiz em aplicativos que se estendem para a barra de título usando o ExtendViewIntoTitleBar API, o controle ajusta automaticamente a posição de seus elementos interativos para evitar a sobreposição com região arrastável.

Um aplicativo que se estende até a barra de título

Se o seu aplicativo especificar a região arrastável chamando o método Window.SetTitleBar da e você preferir que os botões Voltar e de menu se aproximem da parte superior da janela do aplicativo, defina IsTitleBarAutoPaddingEnabled como .

App estendendo-se para a barra de título sem preenchimento extra

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

Observações

Para ajustar ainda mais a posição da área de cabeçalho do NavigationView, substitua o NavigationViewHeaderMargin recurso de tema XAML, por exemplo, nos recursos da Página.

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

Este recurso de tema modifica a margem em torno de NavigationView.Header.

UWP e WinUI 2

Importante

As informações e exemplos neste artigo são otimizados para aplicativos que usam o SDK de Aplicativos Windows e WinUI 3, mas geralmente são aplicáveis a aplicativos UWP que usam WinUI 2. Consulte a referência da API UWP para obter informações e exemplos específicos da plataforma.

Esta seção contém informações que você precisa para usar o controle em um aplicativo UWP ou WinUI 2.

O controle NavigationView para aplicativos UWP está incluído como parte da WinUI 2. Para obter mais informações, incluindo instruções de instalação, consulte WinUI 2. As APIs para esse controle existem nos namespaces Windows.UI.Xaml.Controls e Microsoft.UI.Xaml.Controls .

Recomendamos usar a WinUI 2 mais recente para obter os estilos, modelos e recursos mais atuais para todos os controles. Alguns recursos do NavigationView, como navegação superior e hierárquica , exigem o Windows 10, versão 1809 (SDK 17763) ou posterior, ou WinUI 2.

Para usar o código neste artigo com WinUI 2, use um alias em XAML (usamos muxc) para representar as APIs da Biblioteca da Interface do Usuário do Windows incluídas em seu projeto. Consulte Introdução ao WinUI 2 para obter mais informações.

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

<muxc:NavigationView />