TabView

Il controllo TabView consente di visualizzare un set di schede e il rispettivo contenuto. I controlli TabView sono utili per visualizzare diverse pagine (o documenti) di contenuto, offrendo agli utenti la possibilità di ridisporre, aprire o chiudere nuove schede.

Esempio di TabView

Ottenere WinUI

Logo WinUI

Il controllo TabView richiede WinUI, un pacchetto NuGet che contiene nuovi controlli e funzionalità dell'interfaccia utente per le app di Windows. Per maggiori informazioni, incluse le istruzioni per l'installazione, vedere WinUI.

API WinUI: classe TabView, classe TabViewItem

Suggerimento

In questo documento, useremo l'alias muxc in XAML per rappresentare le API WinUI incluse nel progetto. Abbiamo aggiunto questo alias all'elemento Page: xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

Anche nel code-behind, useremo l'alias muxc in C# per rappresentare le API WinUI incluse nel progetto. Abbiamo aggiunto questa istruzione using all'inizio del file: using muxc = Microsoft.UI.Xaml.Controls;

È il controllo giusto?

In generale, le interfacce utente a schede sono disponibili in uno di due stili distinti che differiscono per funzione e aspetto: le schede statiche sono il tipo di schede che si trovano spesso nelle finestre di impostazioni. Esse contengono un determinato numero di pagine in un ordine fisso che di solito includono contenuto predefinito. Le schede documento sono le schede presenti in un browser, ad esempio in Microsoft Edge. Gli utenti possono creare, rimuovere e ridisporre le schede, spostarle da una finestra a un'altra e modificarne il contenuto.

TabView offre schede documento per le app UWP. Usa un controllo TabView quando:

  • Gli utenti potranno aprire, chiudere o ridisporre dinamicamente le schede.
  • Gli utenti potranno aprire documenti o pagine Web direttamente nelle schede.
  • Gli utenti potranno trascinare e rilasciare le schede da una finestra a un'altra.

Se un controllo TabView non è appropriato per l'app, valutare l'uso di un controllo NavigationView.

Anatomia

L'immagine seguente mostra le parti del controllo TabView. L'oggetto TabStrip dispone di un'intestazione e di un piè di pagina che, a differenza di quanto avviene in un documento, si trovano rispettivamente all'estrema sinistra e all'estrema destra dell'elenco schede.

Anatomia del controllo TabView

L'immagine seguente mostra le parti del controllo TabViewItem. Tieni presente che il contenuto fa effettivamente parte del controllo TabViewItem, anche se è visualizzato all'interno del controllo TabView.

Anatomia del controllo TabViewItem

Creare una visualizzazione a schede

In questo esempio viene creato un controllo TabView semplice con gestori eventi per supportare l'apertura e la chiusura delle schede.

 <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

Esistono diversi modi per sfruttare o estendere le funzionalità di un controllo TabView.

Tabulazione

A partire da SDK per app di Windows 1.6, TabView supporta una modalità CanTearOutTabs che offre un'esperienza avanzata per il trascinamento delle schede in una nuova finestra. Quando questa nuova opzione è abilitata, il trascinamento delle schede è molto simile all'esperienza di trascinamento della scheda in Edge e Chrome in cui viene creata immediatamente una nuova finestra durante il trascinamento, consentendo all'utente di trascinarlo sul bordo dello schermo per ingrandire o bloccare la finestra in un movimento uniforme. Questa implementazione non usa anche le API di trascinamento della selezione, quindi non è interessata da alcuna limitazione in tali API.

Nota

Lo strappo tramite tabulazione è supportato nei processi in esecuzione con privilegi elevati come amministratore.

Associare TabItemsSource a un oggetto TabViewItemCollection

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

Visualizzare le schede del controllo TabView nella barra del titolo di una finestra

Invece di avere schede che occupano ciascuna una propria riga sotto la barra del titolo di una finestra, puoi unire le schede e la barra nella stessa area. In questo modo puoi risparmiare spazio verticale per il contenuto e conferire all'app un aspetto più moderno.

Poiché un utente può riposizionare una finestra trascinandola tramite la barra del titolo, è importante che tale barra non sia totalmente riempita dalle schede. Pertanto, quando visualizzi le schede in una barra del titolo, devi specificare una parte della barra da riservare come area trascinabile. Se non specifichi tale area, l'intera barra del titolo risulterà trascinabile e le schede non potranno ricevere gli eventi di input. Se il controllo TabView verrà visualizzato nella barra del titolo di una finestra, dovrai sempre includere un oggetto TabStripFooter in TabView e contrassegnarlo come area trascinabile.

Per altre informazioni, vedi Personalizzazione della barra del titolo

Schede nella barra del titolo

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

Nota

Per assicurarti che le schede nella barra del titolo non siano ostruite dal contenuto della shell, devi tenere conto delle sovrapposizioni a sinistra e destra. Nei layout da sinistra a destra il margine destro include i pulsanti della barra del titolo e l'area di trascinamento. Nei layout da destra a sinistra avviene l'opposto. I valori di SystemOverlayLeftInset e SystemOverlayRightInset si riferiscono alla sinistra e alla destra fisiche, pertanto inverti anche tali valori in caso di layout da destra a sinistra.

Controllare il comportamento di riversamento

Man mano che la barra si riempie di schede, puoi controllare il modo in cui queste devono essere visualizzate impostando TabView.TabWidthMode.

Valore di TabWidthMode Comportamento
Uguale Man mano che vengono aggiunte nuove schede, tutte le schede vengono compattate orizzontalmente fino a raggiungere una larghezza minima molto piccola.
SizeToContent Le schede avranno sempre le rispettive "dimensioni naturali", ovvero le dimensioni minime necessarie per visualizzare l'icona e l'intestazione. Non verranno espanse o compattate quando vengono aggiunte o chiuse altre schede.

Indipendentemente dal valore scelto, in un determinato momento potrebbero esserci comunque troppe schede da visualizzare nell'elenco schede. In tal caso, verranno visualizzati dei pulsanti dorsali che consentono all'utente di scorrere l'oggetto TabStrip verso sinistra e verso destra.

Indicazioni per la selezione delle schede

La maggior parte degli utenti acquisisce familiarità con le schede documento semplicemente perché le usa in un Web browser. Quando gli utenti usano le schede documento nella tua app, le loro aspettative relativamente al comportamento delle schede si basano su tale esperienza acquisita precedentemente.

Indipendentemente dal modo in cui l'utente interagisce con un set di schede documento, dovrebbe essere sempre presente una scheda attiva. Se l'utente chiude la scheda selezionata o interrompe la scheda selezionata in un'altra finestra, un'altra scheda dovrebbe diventare la scheda attiva. TabView tenta di eseguire questa operazione selezionando automaticamente la scheda successiva. Se esiste un buon motivo per cui l'app dovrebbe consentire un controllo TabView con una scheda non selezionata, l'area di contenuto di TabView sarà vuota.

Navigazione da tastiera

Per impostazione predefinita, il controllo TabView supporta numerosi scenari comuni di spostamento tramite tastiera. Questa sezione illustra la funzionalità incorporata e fornisce consigli su funzionalità aggiuntive che potrebbero essere utili per alcune app.

Comportamento del tasto TAB e dei tasti cursore

Quando lo stato attivo si sposta nell'area dell'oggetto TabStrip, il controllo TabViewItem selezionato ottiene lo stato attivo. L'utente può quindi usare i tasti freccia SINISTRA e DESTRA per spostare lo stato attivo (non la selezione) su altre schede nell'oggetto TabStrip. Lo stato attivo spostato tramite i tasti di direzione viene catturato all'interno dell'elenco schede e del pulsante Aggiungi scheda (+), se presente. Per spostare lo stato attivo dall'area dell'oggetto TabStrip, l'utente può premere il tasto TAB. In questo modo, lo stato attivo verrà spostato sul successivo elemento con stato attivabile.

Spostamento dello stato attivo tramite il tasto TAB

Spostamento dello stato attivo tramite il tasto TAB

I tasti di direzione non eseguono cicli di spostamento dello stato attivo

I tasti di direzione non eseguono cicli di spostamento dello stato attivo

Selezione di una scheda

Quando un controllo TabViewItem ha lo stato attivo, è possibile selezionarlo premendo la BARRA SPAZIATRICE o INVIO.

Usa i tasti di direzione per spostare lo stato attivo e quindi premi la BARRA SPAZIATRICE per selezionare la scheda.

BARRA SPAZIATRICE per selezionare la scheda

Tasti di scelta rapida per la selezione di schede adiacenti

Con CTRL+TAB si seleziona il controllo TabViewItem successivo. Con CTRL+MAIUSC+TAB si seleziona il controllo TabViewItem precedente. A tali fini, viene eseguito un "ciclo" nell'elenco schede. Pertanto, se selezioni la scheda successiva mentre è selezionata l'ultima scheda, verrà selezionata la prima scheda.

Chiusura di una scheda

Con CTRL+F4 verrà generato l'evento TabCloseRequested. Gestisci l'evento e chiudi la scheda, se opportuno.

Indicazioni relative alla tastiera per gli sviluppatori di app

Alcune applicazioni possono richiedere un controllo della tastiera più avanzato. Prendi in considerazione la possibilità di implementare i tasti di scelta rapida seguenti, se appropriati per la tua app.

Avviso

Se aggiungi un controllo TabView a un'app esistente, è probabile che tu abbia già creato tasti di scelta rapida mappati alle combinazioni di tasti usate nelle scelte rapide da tastiera consigliate per TabView. In questo caso, dovrai decidere se mantenere i tasti di scelta rapida esistenti o offrire all'utente un'esperienza intuitiva relativamente alle schede.

  • CTRL+T dovrebbe aprire una nuova scheda. Generalmente, questa scheda viene popolata con un documento predefinito oppure viene creata vuota e con la possibilità di scegliere il relativo contenuto. Se l'utente deve scegliere il contenuto per una nuova scheda, prendi in considerazione la possibilità di spostare lo stato attivo di input sul controllo di selezione del contenuto.
  • CTRL+W dovrebbe chiudere la scheda selezionata. Tenere presente che TabView selezionerà automaticamente la scheda successiva.
  • Con CTRL+MAIUSC+T si dovrebbero aprire le schede chiuse di recente (o, più precisamente, si dovrebbero aprire nuove schede con lo stesso contenuto di quelle chiuse di recente). Inizia dalla scheda chiusa più di recente e procedi a ritroso nel tempo a ogni successivo richiamo del tasto di scelta rapida. Tieni presente che, a tale scopo, sarà necessario mantenere un elenco delle schede chiuse di recente.
  • Con CTRL+1 si dovrebbe selezionare la prima scheda nell'elenco schede. Analogamente, con CTRL+2 si dovrebbe selezionare la seconda scheda, con CTRL+3 si dovrebbe selezionare la terza scheda e così via fino a CTRL+8.
  • Con CTRL+9 si dovrebbe selezionare l'ultima scheda nell'elenco schede, indipendentemente dal numero di schede presenti nell'elenco.
  • Se le schede non offrono soltanto il comando di chiusura, ma ad esempio anche comandi per duplicare o bloccare una scheda, usa un menu di scelta rapida per mostrare tutte le azioni disponibili che è possibile eseguire su una scheda.

Implementare il comportamento della tastiera in stile browser

In questo esempio vengono implementati alcuni dei consigli sopra riportati per un controllo TabView. In particolare, in questo esempio vengono implementati 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;
    }
}