TabView

O controle TabView é uma maneira de exibir um conjunto de guias e seu respectivo conteúdo. TabViews são úteis para exibir várias páginas (ou documentos) de conteúdo e, ao mesmo tempo, dar a um usuário a capacidade de reorganizar, abrir ou fechar novas guias.

Exemplo de um TabView

Obtenha o WinUI

Logotipo do WinUI

O controle TabView exige a WinUI, um pacote NuGet que contém novos controles e recursos de interface do usuário para aplicativos do Windows. Para obter mais informações, incluindo instruções de instalação, confira WinUI.

APIs do WinUI: Classe TabView, Classe TabViewItem

Dica

Neste documento, usamos o alias muxc em XAML para representar a APIs da WinUI que incluímos em nosso projeto. Adicionamos isso ao nosso elemento Page: xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

No code-behind, também usamos o alias muxc em C# para representar a APIs da WinUI que incluímos em nosso projeto. Adicionamos essa instrução using na parte superior do arquivo: using muxc = Microsoft.UI.Xaml.Controls;

Esse é o controle correto?

Em geral, as interfaces do usuário com guias vêm em um dos dois estilos distintos que diferem em função e aparência: guias estáticas são aquelas frequentemente encontradas nas janelas de configurações. Elas contêm um número definido de páginas em uma ordem fixa que geralmente contém conteúdo predefinido. As guias do documento são o tipo de guias encontrado em um navegador, como o Microsoft Edge. Os usuários podem criar, remover e reorganizar guias; mover guias entre janelas; e alterar o conteúdo das guias.

O TabView oferece guias de documento para aplicativos UWP. Use um TabView quando:

  • Os usuários puderem abrir, fechar ou reorganizar tabelas dinamicamente.
  • Os usuários puderem abrir documentos ou páginas da Web diretamente em guias.
  • Os usuários puderem arrastar e soltar as guias entre janelas.

Se um TabView não for apropriado para o aplicativo, use um controle NavigationView.

Anatomia

A imagem abaixo mostra as partes do controle TabView. O TabStrip tem um cabeçalho e um rodapé, mas ao contrário de um documento, o cabeçalho e o rodapé do TabStrip estão no lado mais à esquerda e mais à direita da faixa, respectivamente.

Anatomia do controle TabView

A imagem a seguir mostra as partes do controle TabViewItem. Observe que, embora o conteúdo seja exibido dentro do controle TabView, o conteúdo normalmente faz parte do TabViewItem.

Anatomia do controle TabViewItem

Criar um modo de exibição de guia

Este exemplo cria um TabView simples junto com manipuladores de evento para abrir e fechar guias.

 <muxc:TabView AddTabButtonClick="TabView_AddTabButtonClick"
               TabCloseRequested="TabView_TabCloseRequested"/>
// Add a new Tab to the TabView
private void TabView_AddTabButtonClick(muxc.TabView sender, object args)
{
    var newTab = new muxc.TabViewItem();
    newTab.IconSource = new muxc.SymbolIconSource() { Symbol = Symbol.Document };
    newTab.Header = "New Document";

    // The Content of a TabViewItem is often a frame which hosts a page.
    Frame frame = new Frame();
    newTab.Content = frame;
    frame.Navigate(typeof(Page1));

    sender.TabItems.Add(newTab);
}

// Remove the requested tab from the TabView
private void TabView_TabCloseRequested(muxc.TabView sender, muxc.TabViewTabCloseRequestedEventArgs args)
{
    sender.TabItems.Remove(args.Tab);
}

Comportamento

Há várias maneiras de aproveitar ou estender a funcionalidade de um TabView.

Separador de abas

A partir do SDK do Aplicativo Windows 1.6, o TabView dá suporte a um modo CanTearOutTabs que fornece uma experiência aprimorada para arrastar guias para uma nova janela. Quando essa nova opção está ativada, arrastar a guia é muito parecido com a experiência de arrastar a guia no Edge e no Chrome, onde uma nova janela é criada imediatamente durante o arrasto, permitindo que o usuário a arraste para a borda da tela para maximizar ou ajustar a janela em um movimento suave. Essa implementação também não usa APIs de arrastar e soltar, portanto, não é afetada por nenhuma limitação nessas APIs.

Observação

A remoção de tabulação é suportada em processos executados com privilégios elevados como Administrador.

Associar o TabItemsSource a um TabViewItemCollection

<muxc:TabView TabItemsSource="{x:Bind TabViewItemCollection}" />

Exibir guias TabView na barra de títulos de uma janela

Em vez de fazer as guias ocuparem sua própria linha embaixo do título de uma janela, é possível mesclá-las na mesma área. Isso economiza espaço vertical do seu conteúdo e confere ao seu aplicativo uma sensação moderna.

Como um usuário pode arrastar uma janela por sua barra de títulos para reposicionar a janela, é importante que a barra de títulos não seja completamente preenchida com guias. Portanto, ao exibir guias em uma barra de títulos, é necessário especificar uma parte da barra de títulos para ser reservada como uma área que pode ser arrastada. Se você não especificar uma região que pode ser arrastada, toda a barra de títulos poderá ser arrastada, o que impedirá que suas guias recebam eventos de entrada. Se o TabView for exibido na barra de títulos de uma janela, você sempre deverá incluir um TabStripFooter em seu TabView e marcá-lo como uma região que pode ser arrastada.

Para obter mais informações, confira Personalização da barra de título

Guias na barra de títulos

<muxc:TabView HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <muxc:TabViewItem Header="Home" IsClosable="False">
        <muxc:TabViewItem.IconSource>
            <muxc:SymbolIconSource Symbol="Home" />
        </muxc:TabViewItem.IconSource>
    </muxc:TabViewItem>
    <muxc:TabViewItem Header="Document 0">
        <muxc:TabViewItem.IconSource>
            <muxc:SymbolIconSource Symbol="Document" />
        </muxc:TabViewItem.IconSource>
    </muxc:TabViewItem>
    <muxc:TabViewItem Header="Document 1">
        <muxc:TabViewItem.IconSource>
            <muxc:SymbolIconSource Symbol="Document" />
        </muxc:TabViewItem.IconSource>
    </muxc:TabViewItem>
    <muxc:TabViewItem Header="Document 2">
        <muxc:TabViewItem.IconSource>
            <muxc:SymbolIconSource Symbol="Document" />
        </muxc:TabViewItem.IconSource>
    </muxc:TabViewItem>

    <muxc:TabView.TabStripHeader>
        <Grid x:Name="ShellTitlebarInset" Background="Transparent" />
    </muxc:TabView.TabStripHeader>
    <muxc:TabView.TabStripFooter>
        <Grid x:Name="CustomDragRegion" Background="Transparent" />
    </muxc:TabView.TabStripFooter>
</muxc:TabView>
public MainPage()
{
    this.InitializeComponent();

    var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
    coreTitleBar.ExtendViewIntoTitleBar = true;
    coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;

    Window.Current.SetTitleBar(CustomDragRegion);
}

private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
    if (FlowDirection == FlowDirection.LeftToRight)
    {
        CustomDragRegion.MinWidth = sender.SystemOverlayRightInset;
        ShellTitlebarInset.MinWidth = sender.SystemOverlayLeftInset;
    }
    else
    {
        CustomDragRegion.MinWidth = sender.SystemOverlayLeftInset;
        ShellTitlebarInset.MinWidth = sender.SystemOverlayRightInset;
    }

    CustomDragRegion.Height = ShellTitlebarInset.Height = sender.Height;
}

Observação

Para verificar se as guias na barra de títulos não são obstruídas pelo conteúdo do shell, você deve contabilizar as sobreposições esquerdas e direitas. Em layouts LTR, a inserção direita inclui os botões de legenda e a região de arrastar. O inverso é verdadeiro em RTL. Os valores SystemOverlayLeftInset e SystemOverlayRightInset estão em termos de esquerda e direita físicas, então inverta-os também quando estiverem em RTL.

Controlar comportamento de estouro

Como a barra de guias fica cheia de guias, é possível controlar como elas são exibidas definindo TabView.TabWidthMode.

Valor TabWidthMode Comportamento
Igual À medida que novas guias forem adicionadas, todas elas serão reduzidas horizontalmente até chegarem a uma largura mínima muito pequena.
SizeToContent As guias sempre terão seu "tamanho natural", o tamanho mínimo necessário para exibir seu ícone e cabeçalho. Elas não serão expandidas ou recolhidas conforme novas guias forem adicionadas ou fechadas.

Independentemente do valor escolhido, eventualmente pode haver muitas guias a serem exibidas em sua faixa de guias. Nesse caso, serão exibidos amortecedores de rolagem que permitem que o usuário role a TabStrip para a esquerda e para a direita.

Diretrizes para a seleção de guia

A maioria dos usuários tem experiência com o uso de guias de documentos simplesmente usando um navegador da Web. Quando eles usam guias de documentos em seu aplicativo, a experiência deles informa suas expectativas para a maneira como as guias devem se comportar.

Independentemente de como o usuário interage com um conjunto de guias de documento, sempre deve haver uma guia ativa. Se o usuário fechar a guia selecionada ou dividir a guia selecionada em outra janela, outra guia deverá se tornar a guia ativa. TabView tenta fazer isso automaticamente selecionando a próxima guia. Se você tiver um bom motivo para que seu aplicativo permita um TabView com uma guia não selecionada, a área de conteúdo do TabView ficará simplesmente em branco.

Navegação pelo teclado

O TabView é compatível com muitos cenários de navegação de teclado comuns por padrão. Esta seção explica a funcionalidade interna e fornece recomendações sobre funcionalidades adicionais que podem ser úteis para alguns aplicativos.

Comportamento-chave da guia e do cursor

Quando o foco passa para a área TabStrip, o TabViewItem selecionado ganha foco. O usuário pode usar as teclas de seta para a esquerda e para a direita para mover o foco (não seleção) para outras guias no TabStrip. O foco da seta é interceptado dentro da faixa de guias e do botão adicionar guia (+), se houver um. Para mover o foco para fora da área de TabStrip, o usuário pode pressionar a tecla Tab, que moverá o foco para o próximo elemento de foco.

Mover o foco por meio de Tab

Mover o foco por meio de tab

As teclas de seta não circulam o foco

As teclas de seta não circulam o foco

Selecionar uma guia

Quando um TabViewItem tiver foco, pressionar Espaço ou Enter selecionará esse TabViewItem.

Use as teclas de seta para mover o foco e pressione Espaço para selecionar a guia.

Espaço para selecionar a guia

Atalhos para selecionar guias adjacentes

Ctrl + Tab selecionará o próximo TabViewItem. Ctrl + Shift + Tab selecionará o TabViewItem anterior. Para essas finalidades, a lista de guias está "em loop"; portanto, selecionar a próxima guia enquanto a última estiver selecionada fará a primeira guia ficar selecionada.

Fechar uma guia

Pressionar Ctrl + F4 gerará o evento TabCloseRequested. Manipule o evento e feche a guia, se apropriado.

Diretrizes de teclado para Desenvolvedores de Aplicativo

Alguns aplicativos podem exigir um controle de teclado mais avançado. Considere implementar os seguintes atalhos se eles forem apropriados para seu aplicativo.

Aviso

Se estiver adicionando um TabView a um aplicativo existente, você já poderá ter criado atalhos de teclado mapeados para as combinações de teclas dos atalhos de teclado TabView recomendados. Nesse caso, você precisará considerar se deseja manter seus atalhos existentes ou oferecer uma experiência de guia intuitiva para o usuário.

  • Ctrl + T deve abrir uma nova guia. Geralmente, essa guia é preenchida com um documento predefinido ou é criada vazia com uma maneira simples de escolher seu conteúdo. Se o usuário precisar escolher o conteúdo para uma nova guia, considere fornecer o foco de entrada para o controle de seleção de conteúdo.
  • Ctrl + W deve fechar a guia selecionada. Lembre-se, o TabView seleciona a próxima guia automaticamente.
  • Ctrl + Shift + T deve abrir as guias recentemente fechadas (ou, mais precisamente, abrir novas guias com o mesmo conteúdo que as guias fechadas recentemente). Comece com a guia fechada mais recentemente e mova-se para trás no tempo para cada vez anterior em que o atalho foi invocado. Observe que isso exigirá a manutenção de uma lista de guias fechadas recentemente.
  • Ctrl + 1 deve selecionar a primeira guia na lista de guias. Da mesma forma, Ctrl + 2 deve selecionar a segunda guia, Ctrl + 3 deve selecionar a terceira e assim por diante até Ctrl + 8.
  • Ctrl + 9 deve selecionar a última guia da lista, independentemente de quantas guias estão nela.
  • Se as guias oferecerem mais do que apenas o comando fechar (como duplicar ou fixar uma guia), use um menu de contexto para mostrar todas as ações disponíveis que podem ser executadas em uma guia.

Implementar comportamento de teclado do estilo do navegador

Esse exemplo implementa várias das recomendações acima em um TabView. Especificamente, esse exemplo implementa Ctrl + T, Ctrl + W, Ctrl + 1-8 e Ctrl + 9.

<muxc:TabView x:Name="TabRoot">
    <muxc:TabView.KeyboardAccelerators>
        <KeyboardAccelerator Key="T" Modifiers="Control" Invoked="NewTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="W" Modifiers="Control" Invoked="CloseSelectedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number1" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number2" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number3" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number4" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number5" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number6" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number7" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number8" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
        <KeyboardAccelerator Key="Number9" Modifiers="Control" Invoked="NavigateToNumberedTabKeyboardAccelerator_Invoked" />
    </muxc:TabView.KeyboardAccelerators>
    <!-- ... some tabs ... -->
</muxc:TabView>
private void NewTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
    // Create new tab.
    var newTab = new muxc.TabViewItem();
    newTab.IconSource = new muxc.SymbolIconSource() { Symbol = Symbol.Document };
    newTab.Header = "New Document";

    // The Content of a TabViewItem is often a frame which hosts a page.
    Frame frame = new Frame();
    newTab.Content = frame;
    frame.Navigate(typeof(Page1));

    TabRoot.TabItems.Add(newTab);
}

private void CloseSelectedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
    // Only remove the selected tab if it can be closed.
    if (((muxc.TabViewItem)TabRoot.SelectedItem).IsClosable)
    {
        TabRoot.TabItems.Remove(TabRoot.SelectedItem);
    }
}

private void NavigateToNumberedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
    int tabToSelect = 0;

    switch (sender.Key)
    {
        case Windows.System.VirtualKey.Number1:
            tabToSelect = 0;
            break;
        case Windows.System.VirtualKey.Number2:
            tabToSelect = 1;
            break;
        case Windows.System.VirtualKey.Number3:
            tabToSelect = 2;
            break;
        case Windows.System.VirtualKey.Number4:
            tabToSelect = 3;
            break;
        case Windows.System.VirtualKey.Number5:
            tabToSelect = 4;
            break;
        case Windows.System.VirtualKey.Number6:
            tabToSelect = 5;
            break;
        case Windows.System.VirtualKey.Number7:
            tabToSelect = 6;
            break;
        case Windows.System.VirtualKey.Number8:
            tabToSelect = 7;
            break;
        case Windows.System.VirtualKey.Number9:
            // Select the last tab
            tabToSelect = TabRoot.TabItems.Count - 1;
            break;
    }

    // Only select the tab if it is in the list
    if (tabToSelect < TabRoot.TabItems.Count)
    {
        TabRoot.SelectedIndex = tabToSelect;
    }
}