Partilhar via


Visualização de tabulação

O controle TabView é uma maneira de exibir um conjunto de guias e seu respetivo conteúdo. Os controles TabView são úteis para exibir várias páginas (ou documentos) de conteúdo enquanto permitem que um usuário reorganize, feche ou abra novas guias.

exemplo de um TabView

Será este o controlo correto?

Em geral, as interfaces do usuário com guias vêm em um de dois estilos distintos que diferem em função e aparência:

  • Os separadores estáticos são o tipo de separadores frequentemente encontrados nas janelas de definições. Eles contêm um número definido de páginas em uma ordem fixa que geralmente contêm conteúdo predefinido.
  • Guias de Documento são o tipo de guias encontradas num navegador, como o Microsoft Edge. Os utilizadores podem criar, remover e reorganizar separadores; mover separadores entre janelas; e alterar o conteúdo dos separadores.

Por padrão, TabView está configurado para fornecer abas de documento. Recomendamos o TabView quando os usuários puderem:

  • Abra, feche ou reorganize dinamicamente os separadores.
  • Abra documentos ou páginas da Web diretamente em guias.
  • Arraste e solte guias entre as janelas.

A API TabView permite configurar o controle para guias estáticas. No entanto, para seguir as diretrizes de design do Windows, caso haja mais do que alguns itens de navegação estática, considere usar um controlo NavigationView .

Anatomia

A interface de utilizador com separadores é criada com um controle TabView e um ou mais controles TabViewItem. O TabView hospeda instâncias de TabViewItem, que representa uma única guia e seu conteúdo.

Peças TabView

Esta imagem mostra as partes do controlo de TabView. A faixa de tabulação tem um cabeçalho e um rodapé, mas, ao contrário de um documento, o cabeçalho e o rodapé da faixa de tabulação estão na extremidade esquerda e na extrema direita da faixa, respectivamente.

Esta imagem mostra as partes do controle de exibição de guia. A faixa de tabulação contém quatro abas e tem um cabeçalho e rodapé, que estão na extrema esquerda e extrema direita da faixa, respectivamente.

TabViewItem componentes

Esta imagem mostra as partes do controlo TabViewItem. Embora o conteúdo seja exibido dentro do controle TabView, o conteúdo é, na verdade, uma parte do TabViewItem.

Esta imagem mostra as partes do controle de item de exibição de guia. É selecionada uma guia individual, que tem um ícone e um rótulo, com uma área de conteúdo abaixo da guia.

Recomendações

Seleção de aba

A maioria dos usuários tem experiência usando guias de documentos simplesmente usando um navegador da web. Quando utilizam as abas de documentos na sua aplicação, a experiência deles molda as suas expectativas sobre como essas abas devem comportar-se.

Não importa 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 quebrar a guia selecionada em outra janela, outra guia deve se tornar a guia ativa. TabView tenta fazer isso selecionando automaticamente 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 por teclado

TabView suporta muitos cenários comuns de navegação por teclado 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 das teclas de tabulação e cursor

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

Mover o foco via Tab

Mover o foco através da tecla tab

As teclas de seta não alternam o foco

Teclas de seta não alternam o foco

Selecionar um separador

Quando um TabViewItem tiver foco, pressione Espaço ou Enter para selecionar esse TabViewItem.

Use as setas para mover o foco e pressione Espaço para selecionar a guia.

Espaço para selecionar separador

Atalhos para selecionar separadores adjacentes

Pressione Ctrl+Tab para selecionar o próximo TabViewItem. Pressione Ctrl+Shift+Tab para selecionar o TabViewItem anterior. Para esses fins, a lista de guias é "em loop", portanto, selecionar a próxima guia enquanto a última guia está selecionada fará com que a primeira guia seja selecionada.

Fechar um separador

Pressione Ctrl + F4 para desencadear o evento TabCloseRequested. Manipule o evento e feche a guia, se apropriado.

Dica

Para obter mais informações, consulte Orientações de teclado para desenvolvedores mais adiante neste artigo.

Criar uma vista de separador

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

Os exemplos nesta seção mostram uma variedade de maneiras de configurar um controle de TabView.

Itens da vista de tabulação

Cada aba em um TabView é representada por um controlo TabViewItem, que inclui tanto a aba mostrada na faixa de guias como o conteúdo mostrado abaixo dela.

Configurar um separador

Para cada TabViewItem, você pode definir um cabeçalho e um ícone e especificar se o usuário pode fechar a guia.

  • A propriedade Header normalmente é definida como um valor de cadeia de caracteres que fornece um rótulo descritivo para a guia. No entanto, a propriedade Header pode ser qualquer objeto. Você também pode usar a propriedade HeaderTemplate para especificar um DataTemplate que define como os dados de cabeçalho acoplados devem ser exibidos.
  • Defina a propriedade IconSource para especificar um ícone para a guia.
  • Por padrão, a guia mostra um botão fechar. Você pode definir a propriedade IsClosable como false para garantir que um usuário não possa fechar a guia.

Para o TabView, você pode configurar várias opções que se aplicam a todas as guias.

  • Por padrão, o botão fechar (X) é sempre mostrado para guias que podem ser fechadas. Você pode definir a propriedade CloseButtonOverlayMode como para alterar esse comportamento. Nesse caso, o separador selecionado sempre mostra o botão fechar se for possível fechá-lo, mas os separadores não selecionados mostram o botão fechar somente quando o separador é possível de fechar e o utilizador tem o ponteiro sobre ele.
  • Você pode definir a propriedade TabWidthMode para alterar como as guias são dimensionadas. (A propriedade é ignorada em .) Estas são as opções na enumeração TabViewWidthMode:
    • Equal - Cada separador tem a mesma largura. Este é o padrão.
    • SizeToContent - Cada separador ajusta a sua largura ao conteúdo dentro do separador.
    • Compact - Os separadores não selecionados recolhem para mostrar apenas o respetivo ícone. A guia selecionada é ajustada para exibir o conteúdo dentro da guia.

Conteúdo

Os elementos exibidos na guia selecionada são adicionados à propriedade Content do TabViewItem. TabViewItem é um ContentControl, portanto, você pode adicionar qualquer tipo de objeto como conteúdo. Você também pode aplicar um DataTemplate à propriedade ContentTemplate. Consulte a classe ContentControl para obter mais informações.

Os exemplos neste artigo mostram um caso simples de adição de texto diretamente ao elemento Content em XAML. No entanto, a interface do usuário real é normalmente mais complexa. Uma maneira comum de adicionar uma interface do utilizador complexa como o conteúdo de um separador é encapsulá-la num UserControl ou numa Página, e adicioná-la como o conteúdo do TabViewItem. Este exemplo pressupõe que seu aplicativo tenha um UserControl XAML chamado PictureSettingsControl.

<TabViewItem>
    <TabViewItem.Content>
        <local:PictureSettingsControl/>
    </TabViewItem.Content>
</TabViewItem>

Separadores estáticos

Este exemplo mostra um TabView simples com duas abas estáticas . Ambos os itens de guia são adicionados em XAML como conteúdo do TabView.

Para tornar um TabView estático, use estas configurações:

  • Defina a propriedade IsAddTabButtonVisible como false para ocultar o botão de adicionar separador e impedir que o evento AddTabButtonClick seja gerado.
  • Defina a propriedade CanReorderTabs como para impedir que o usuário arraste guias para uma ordem diferente.
  • Em cada TabViewItem , defina a propriedade IsClosable como false para ocultar a guia fechar botão impedir que o usuário gere o evento TabCloseRequested.
<TabView VerticalAlignment="Stretch"
         IsAddTabButtonVisible="False"
         CanReorderTabs="False">
    <TabViewItem Header="Picture" IsClosable="False">
        <TabViewItem.IconSource>
            <SymbolIconSource Symbol="Pictures"/>
        </TabViewItem.IconSource>
        <TabViewItem.Content>
            <StackPanel Padding="12">
                <TextBlock Text="Picture settings" 
                    Style="{ThemeResource TitleTextBlockStyle}"/>
            </StackPanel>
        </TabViewItem.Content>
    </TabViewItem>
    <TabViewItem Header="Sound" IsClosable="False">
        <TabViewItem.IconSource>
            <SymbolIconSource Symbol="Audio"/>
        </TabViewItem.IconSource>
        <TabViewItem.Content>
            <StackPanel Padding="12">
                <TextBlock Text="Sound settings" 
                    Style="{ThemeResource TitleTextBlockStyle}"/>
            </StackPanel>
        </TabViewItem.Content>
    </TabViewItem>
</TabView>

Separadores de documentos

Por predefinição, o TabView está configurado como guias de documento. O utilizador pode adicionar novos separadores, reorganizar separadores e fechar separadores. Nessa configuração, precisas manipular os eventos AddTabButtonClick e TabCloseRequested para habilitar a funcionalidade.

Quando as guias são adicionadas a um TabView, pode eventualmente haver muitas guias para exibir em sua faixa de guias. Neste caso, aparecerão controlos de navegação que permitem ao utilizador deslizar a barra de abas para a esquerda e para a direita para aceder às abas ocultas.

Este exemplo cria um TabView simples junto com manipuladores de eventos para suportar a abertura e o fechamento de abas. O manipulador de eventos TabView_AddTabButtonClick mostra como adicionar um TabViewItem no código.

<TabView VerticalAlignment="Stretch"
         AddTabButtonClick="TabView_AddTabButtonClick"
         TabCloseRequested="TabView_TabCloseRequested">
    <TabViewItem Header="Home" IsClosable="False">
        <TabViewItem.IconSource>
            <SymbolIconSource Symbol="Home" />
        </TabViewItem.IconSource>
        <TabViewItem.Content>
            <StackPanel Padding="12">
                <TextBlock Text="TabView content" 
                           Style="{ThemeResource TitleTextBlockStyle}"/>
            </StackPanel>
        </TabViewItem.Content>
    </TabViewItem>
</TabView>
// Add a new tab to the TabView.
private void TabView_AddTabButtonClick(TabView sender, object args)
{
    var newTab = new TabViewItem();
    newTab.Header = $"New Document {sender.TabItems.Count}";
    newTab.IconSource = new SymbolIconSource() { Symbol = Symbol.Document };
    newTab.Content = new TextBlock() { Text = $"Content for new tab {sender.TabItems.Count}.",
                                       Padding = new Thickness(12) };
    sender.TabItems.Add(newTab);
    sender.SelectedItem = newTab;
}

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

Fechar a janela quando o último separador estiver fechado

Se todas as guias do seu aplicativo forem fecháveis e a janela do aplicativo deve fechar quando a última guia for fechada, deverá também fechar a janela no manipulador de eventos TabCloseRequested.

Primeiro, no arquivo App.xaml.cs, adicione uma propriedade pública que permitirá que você acesse a instância Window do Page que hospeda o TabView.

public partial class App : Application
{
    // ... code removed.

    public Window? Window => m_window; // Add this.
    private Window? m_window;
}

Em seguida, modifique o manipulador de eventos TabCloseRequested para chamar Window.Close se todas as guias tiverem sido removidas do TabView.

// Remove the requested tab from the TabView.
// If all tabs have been removed, close the Window.
private void TabView_TabCloseRequested(TabView sender, 
                                       TabViewTabCloseRequestedEventArgs args)
{
    sender.TabItems.Remove(args.Tab);

    if (sender.TabItems.Count == 0)
    {
        var window = (Application.Current as App)?.Window as MainWindow;
        window?.Close();
    }
}

Observação

Este exemplo funciona para um aplicativo com uma única janela (MainWindow). Se a sua aplicação tiver várias janelas, ou se tiver ativado a separação de abas, precisará rastrear as janelas e, em seguida, encontrar a correta para fechar. Veja a próxima seção para um exemplo disso.

Remoção de tabulação

Tab tear-out descreve o que acontece quando um usuário arrasta uma guia para fora da faixa de guias do TabView e a move para outro controle TabView, normalmente em uma nova janela.

A partir do Windows App SDK 1.6, TabView tem uma propriedade CanTearOutTabs que você pode definir para fornecer uma experiência aprimorada para arrastar guias para uma nova janela. Quando um usuário arrasta uma guia para fora da faixa de guias com essa opção ativada, uma nova janela é imediatamente criada durante o arrasto, permitindo que o usuário a arraste até a borda da tela para maximizar ou encaixar 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.

Quando você define a propriedade CanTearOutTabs como , isso faz com que os eventos de de exclusão de guia sejam gerados em vez de eventos de arrastar e soltar. Para implementar o desmonte de guias, você deve manipular estes eventos:

  • TabTearOutWindowRequested

    Esse evento ocorre quando uma guia é arrastada pela primeira vez para fora da faixa de guias. Utilize-o para criar uma nova janela e TabView para a qual a guia será movida.

  • TabTearOutRequested

    Esse evento ocorre após uma nova janela ter sido fornecida. Manipule-o para mover a guia rasgada do TabView de origem para um TabView na nova janela.

  • ExternalTornOutTabsSoltando

    Esse evento ocorre quando uma guia rasgada é arrastada sobre um TabView existente. Manipule-o no TabView que está recebendo a guia rasgada para indicar se a guia deve ou não ser aceita.

  • ExternalTornOutTabsDropped

    Esse evento ocorre quando uma guia rasgada é arrastada sobre um TabView existente e o evento ExternalTornOutTabsDropping indicou que o soltar é permitido. Manipule-o no TabView que está recebendo a guia rasgada para remover a guia do TabView de origem e inseri-la no TabView de recebimento no índice especificado.

Esses eventos não são gerados quando a eliminação de tabulação está habilitada: TabDragStarting, TabStripDragOver, TabStripDrop, TabDragCompleted, TabDroppedOutside.

Atenção

Tab tear-out é suportado em processos que executam em modo elevado como Administrador.

Os exemplos a seguir mostram como implementar os manipuladores de eventos para dar suporte ao desmonte de guias.

Configurar TabView

Este XAML define a propriedade CanTearOutTabs como true e configura os manipuladores de eventos de desmontagem de guia.

<TabView x:Name="tabView"
     CanTearOutTabs="True"
     TabTearOutWindowRequested="TabView_TabTearOutWindowRequested"
     TabTearOutRequested="TabView_TabTearOutRequested"
     ExternalTornOutTabsDropping="TabView_ExternalTornOutTabsDropping"
     ExternalTornOutTabsDropped="TabView_ExternalTornOutTabsDropped">
    <!-- TabView content -->
</TabView>

Criar e acompanhar uma nova janela

A remoção de abas requer que crie e gerencie novas janelas na sua aplicação.

Dica

O aplicativo WinUI Gallery inclui uma classe WindowHelper que facilita o gerenciamento de janelas em seu aplicativo. Você pode copiá-lo do GitHub no repositório WinUI Gallery: WindowHelper.cs. Recomendamos esta classe auxiliar para implementar o desmonte de guias. Consulte o TabViewWindowingSamplePage no GitHub para ver como ele é usado.

Neste artigo, os métodos auxiliares são copiados do WindowHelper.cs, mas são modificados e mostrados em linha para facilitar a leitura.

Aqui, uma lista para rastrear todas as janelas ativas é criada em App.xaml.cs. O método OnLaunched é atualizado para rastrear a janela após a sua criação. (Isso não é necessário se você usar a classe WindowHelper.)

static public List<Window> ActiveWindows = new List<Window>();

protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();
    // Track this window.
    ActiveWindows.Add(m_window);
    m_window.Activate();
}

Quando a remoção de tabulação começa, uma nova janela é solicitada. Aqui, a variável tabTearOutWindow fornece acesso à nova janela depois que ela é criada. Os métodos auxiliares CreateWindow e TrackWindow criam uma nova janela e a adicionam à lista de acompanhamento de janelas ativa.

Depois de criar a nova janela, você precisa criar uma nova página e defini-la como o conteúdo da janela. O novo Page deve conter um controle TabView para o qual você moverá a guia rasgada no manipulador de eventos TabTearOutRequested.

Dica

Neste exemplo, criamos uma nova classe MainPage, pois ela contém apenas um TabView vazio (nenhuma guia é adicionada diretamente em XAML). Se MainPage incluir outros elementos da interface do usuário que não devem aparecer na janela rasgada, você poderá criar uma página separada que inclua apenas os elementos necessários (incluindo pelo menos um TabView) e criar uma instância dessa página.

Finalmente, atribua o AppWindow.Id da nova janela à propriedade args.NewWindowId. Isso será usado na propriedade TabViewTabTearOutRequestedEventArgs.NewWindowId para que seja possível aceder à janela a partir desse manipulador de eventos.

private Window? tabTearOutWindow = null;

private void TabView_TabTearOutWindowRequested(TabView sender, TabViewTabTearOutWindowRequestedEventArgs args)
{
    tabTearOutWindow = CreateWindow();
    tabTearOutWindow.Content = new MainPage();
    // Optional window setup, such as setting the icon or
    // extending content into the title bar happens here.
    args.NewWindowId = tabTearOutWindow.AppWindow.Id;
}

private Window CreateWindow()
{
    Window newWindow = new Window
    {
        SystemBackdrop = new MicaBackdrop()
    };
    newWindow.Title = "Torn Out Window";
    TrackWindow(newWindow);
    return newWindow;
}

private void TrackWindow(Window window)
{
    window.Closed += (sender, args) => {
        App.ActiveWindows.Remove(window);
    };
    App.ActiveWindows.Add(window);
}

Fechar uma janela quando o último separador estiver fechado

Como mencionado anteriormente, você pode querer fechar a janela quando a última guia em um TabView é fechada. Se o seu aplicativo tiver várias janelas, você precisará encontrar a janela correta para fechar na sua lista de janelas rastreadas. Este exemplo mostra como fazer isso.

// Remove the requested tab from the TabView.
// If all tabs have been removed, close the Window.
private void TabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
{
    sender.TabItems.Remove(args.Tab);

    if (sender.TabItems.Count == 0)
    {
        GetWindowForElement(this)?.Close();
    }
}

public Window? GetWindowForElement(UIElement element)
{
    if (element.XamlRoot != null)
    {
        foreach (Window window in App.ActiveWindows)
        {
            if (element.XamlRoot == window.Content.XamlRoot)
            {
                return window;
            }
        }
    }
    return null;
}

Mover o separador para a nova janela

Depois que a nova janela for fornecida, você precisará remover a guia rasgada do sender TabView e adicioná-la ao TabView na nova janela. Neste exemplo, o método auxiliar public AddTabToTabs permite que você acesse o TabView na nova instância do MainPage a partir da instância da página original para adicionar a guia rasgada a ela.

private void TabView_TabTearOutRequested(TabView sender, TabViewTabTearOutRequestedEventArgs args)
{
    if (tabTearOutWindow?.Content is MainPage newPage
        && args.Tabs.FirstOrDefault() is TabViewItem tab)
    {
        sender.TabItems.Remove(tab);
        newPage.AddTabToTabs(tab);
    }
}

// This method provides access to the TabView from
// another page instance so you can add the torn-out tab.
public void AddTabToTabs(TabViewItem tab)
{
    tabView.TabItems.Add(tab);
}

Arraste uma aba rasgada para outra TabView

Quando uma guia é arrancada e colocada em uma nova janela, como mostrado nas etapas anteriores, uma das duas coisas pode acontecer:

  • O usuário pode soltar a guia e ela permanece na nova janela. O processo de desmantelamento termina aqui e não são gerados mais eventos.
  • O usuário pode continuar a arrastar a guia rasgada de volta para um controle TabView existente. Nesse caso, o processo continua e vários outros eventos são gerados para permitir que você remova a guia do TabView original e insira a guia externa em um TabView existente.

Quando a guia é arrastada sobre o TabView existente, o evento ExternalTornOutTabsDropping é gerado. No manipulador de eventos, pode-se determinar se a inserção da guia neste TabView é permitida. Na maioria dos casos, você só precisa definir a propriedade args.AllowDrop como true. No entanto, se você precisar realizar alguma verificação antes de definir essa propriedade, você pode fazer isso aqui. Se AllowDrop estiver definido como false, a ação de arrastar a aba continuará, e o evento ExternalTornOutTabsDropped não será gerado.

private void TabView_ExternalTornOutTabsDropping(TabView sender, 
                        TabViewExternalTornOutTabsDroppingEventArgs args)
{
    args.AllowDrop = true;
}

Se AllowDrop estiver definido como true no manipulador de eventos ExternalTornOutTabsDropping, o evento ExternalTornOutTabsDropped será imediatamente gerado.

Observação

O no nome do evento não corresponde diretamente à ideia de uma ação de soltar nas APIs de arrastar e soltar. Aqui, o utilizador não precisa libertar a guia para executar a ação drop. O evento é gerado enquanto o separador é mantido sobre a barra de separadores, e o código é executado para largar o separador no TabView.

O manipulador de eventos ExternalTornOutTabsDropped segue o mesmo padrão do evento TabTearOutRequested, mas invertido; você precisa remover a guia do TabView de origem e inseri-lo no sender TabView.

O sender TabView é o controle no qual a guia está sendo inserida, portanto, usamos o método auxiliar GetParentTabView para localizar a guia de origem. Ele começa com o TabViewItem rasgado e usa VisualTreeHelper para subir a árvore visual e encontrar o TabView ao qual o item pertence. Depois que o TabView é encontrado, o TabViewItem é removido de sua coleção de TabItems e inserido na coleção do TabView no índice especificado por DropIndex.

private void TabView_ExternalTornOutTabsDropped(TabView sender, 
                             TabViewExternalTornOutTabsDroppedEventArgs args)
{
    if (args.Tabs.FirstOrDefault() is TabViewItem tab)
    {
        GetParentTabView(tab)?.TabItems.Remove(tab);
        sender.TabItems.Insert(args.DropIndex, tab);
    }
}

// Starting with the TabViewItem, walk up the
// visual tree until you get to the TabView.
private TabView? GetParentTabView(TabViewItem tab)
{
    DependencyObject current = tab;
    while (current != null)
    {
        if (current is TabView tabView)
        {
            return tabView;
        }
        current = VisualTreeHelper.GetParent(current);
    }
    return null;
}

Dica

Se estiver a usar o Windows Community Toolkit, pode utilizar o método auxiliar FindAscendant nas DependencyObjectExtensions do toolkit em vez de GetParentTabView.

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

Em vez de fazer com que as guias ocupem sua própria linha abaixo da barra de título de uma janela, você pode mesclar as duas na mesma área. Isso economiza espaço vertical para seu conteúdo e dá ao seu aplicativo uma sensação moderna.

Como um usuário pode arrastar uma janela pela barra de título para reposicioná-la, é importante que a barra de título não esteja completamente preenchida com guias. Portanto, ao exibir guias em uma barra de título, você deve especificar uma parte da barra de título a ser reservada como uma área arrastável. Se você não especificar uma região arrastável, toda a barra de título será arrastável, o que impede que suas guias recebam eventos de entrada. Se o seu TabView for exibido na barra de título de uma janela, deve sempre incluir um TabStripFooter no seu TabView e marcá-lo como uma região arrastável.

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

Separadores na barra de título

<TabView VerticalAlignment="Stretch">
    <TabViewItem Header="Home" IsClosable="False">
        <TabViewItem.IconSource>
            <SymbolIconSource Symbol="Home" />
        </TabViewItem.IconSource>
    </TabViewItem>

    <TabView.TabStripFooter>
        <Grid x:Name="CustomDragRegion" Background="Transparent" />
    </TabView.TabStripFooter>
</TabView>
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    var currentWindow = (Application.Current as App)?.Window as MainWindow;
    currentWindow.ExtendsContentIntoTitleBar = true;
    currentWindow.SetTitleBar(CustomDragRegion);
    CustomDragRegion.MinWidth = 188;
}

Observação

A forma como obtém uma referência à janela (currentWindow) pode variar dependendo da forma como controla as janelas na sua aplicação. Para obter mais informações, consulte Fechar a janela quando a última guia é fechada e Criar e rastrear uma nova janela neste artigo.

Orientação de teclado para desenvolvedores

Dica

Para obter mais informações sobre o suporte de teclado incorporado, consulte Navegação por teclado anteriormente neste artigo.

Algumas aplicações podem necessitar de um controlo de teclado mais avançado. Considere implementar os seguintes atalhos se eles forem apropriados para seu aplicativo.

Advertência

Se estiveres a adicionar um TabView a uma aplicação existente, talvez já tenhas criado atalhos de teclado mapeados para as combinações de teclas dos atalhos de teclado TabView recomendados. Neste caso, você terá que considerar se deseja manter seus atalhos existentes ou oferecer uma experiência de guia intuitiva para o usuário.

  • Ctrl + T deve abrir um novo separador. Geralmente, esta 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 dar foco de entrada ao controle de seleção de conteúdo.
  • Ctrl + W deve fechar a guia selecionada. Lembre-se, TabView selecionará a próxima guia automaticamente.
  • Ctrl + Shift + T deve abrir separadores recentemente fechados (ou, de forma mais precisa, abrir separadores novos com o mesmo conteúdo dos separadores recentemente fechados). Comece com a guia fechada mais recentemente e retroceda no tempo para cada vez que o atalho for invocado. Note que isto exigirá a manutenção de uma lista de abas 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 através de Ctrl + 8.
  • Ctrl + 9 deve selecionar a última guia na lista de guias, independentemente de quantas guias estão na lista.
  • 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 o comportamento de teclado ao estilo do navegador

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

<TabView>
    <!-- ... some tabs ... -->
    <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" />
    </TabView.KeyboardAccelerators>
</TabView>

private void NewTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender,
                                      KeyboardAcceleratorInvokedEventArgs args)
{
    // Create new tab.
    TabView senderTabView = (TabView)args.Element;
    if (senderTabView != null)
    {
        // (Click handler defined in previous example.)
        TabView_AddTabButtonClick(senderTabView, new EventArgs());
    }
    args.Handled = true;
}

private void CloseSelectedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender,
                                                KeyboardAcceleratorInvokedEventArgs args)
{
    TabView tabView = (TabView)args.Element;
    TabViewItem tab = (TabViewItem)tabView.SelectedItem;
    // Only remove the selected tab if it can be closed.
    if (tabView is not null &&
        tab.IsClosable == true)
    {
        tabView.TabItems.Remove(tab);
    }
    args.Handled = true;
}

private void NavigateToNumberedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender,
                                                     KeyboardAcceleratorInvokedEventArgs args)
{
    TabView tabView = (TabView)args.Element;
    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 = tabView.TabItems.Count - 1;
            break;
    }

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

UWP e WinUI 2

Importante

As informações e os exemplos neste artigo são otimizados para aplicativos que usam o SDK de Aplicativo 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 TabView 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 no namespace Microsoft.UI.Xaml.Controls.

As APIs de separação de guias não estão incluídas na versão WinUI 2 do TabView.

Recomendamos usar o mais recente WinUI 2 para obter os estilos, modelos e recursos mais atuais para todos os controles. WinUI 2.2 ou posterior inclui um novo modelo para este controle que usa cantos arredondados. Para obter mais informações, consulte Raio de canto.

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:TabView />