Condividi tramite


Visualizzazione a schede

Il controllo TabView consente di visualizzare un set di schede e il rispettivo contenuto. I controlli TabView sono utili per visualizzare più pagine (o documenti) di contenuto, consentendo all'utente di riorganizzare, chiudere o aprire nuove schede.

Esempio di un TabView

È il controllo giusto?

In generale, le interfacce utente a schede sono disponibili in uno dei due stili distinti che differiscono in funzione e aspetto:

  • Le schede statiche sono il tipo di schede spesso presenti nelle finestre delle 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.

Per impostazione predefinita, TabView è configurato per fornire schede dei documenti. È consigliabile usare TabView quando gli utenti potranno:

  • Aprire, chiudere o ridisporre le schede in modo dinamico.
  • Aprire documenti o pagine Web direttamente nelle schede.
  • Trascina le schede tra le finestre.

L'API TabView consente di configurare il controllo per le schede statiche. Tuttavia, per seguire le linee guida per la progettazione di Windows e se sono presenti più di alcuni elementi di spostamento statici, è consigliabile usare un controllo NavigationView .

Anatomia

L'interfaccia utente a schede viene creata con un controllo TabView e uno o più controlli TabViewItem. TabView ospita le istanze di TabViewItem, che rappresenta una singola scheda e il relativo contenuto.

Componenti di TabView

Questa immagine mostra le parti del controllo TabView . La striscia di schede ha un'intestazione e un piè di pagina, ma, a differenza di un documento, l'intestazione e il piè di pagina della striscia di schede si trovano rispettivamente all'estrema sinistra e all'estrema destra della striscia.

Questa immagine mostra le parti del controllo di visualizzazione a schede. La barra delle schede contiene quattro schede e ha un'intestazione e un piè di pagina, rispettivamente all'estrema sinistra e all'estrema destra della barra.

Parti di TabViewItem

Questa immagine mostra le parti del controllo TabViewItem . Anche se il contenuto viene visualizzato all'interno del controllo TabView, il contenuto è effettivamente parte di TabViewItem.

Questa immagine mostra le parti del controllo elemento della visualizzazione schede. Viene selezionata una singola scheda, con un'icona e un'etichetta, con un'area di contenuto sotto la scheda.

Consigli

Selezione scheda

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 nella barra delle schede. 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 fuori dall'area della barra di schede, l'utente può premere il tasto Tab, che sposterà lo stato attivo sul prossimo elemento attivabile.

Sposta il focus tramite Tab

Sposta lo stato attivo tramite Tab

I tasti di direzione non cambiano il focus

I tasti di direzione non spostano il focus ciclicamente

Selezione di una scheda

Quando un oggetto TabViewItem ha lo stato attivo, premere Spazio o INVIO per selezionare l'elemento TabViewItem.

Usare i tasti di direzione per spostare lo stato attivo, quindi premere Spazio per selezionare la scheda.

Spazio per selezionare la scheda

Tasti di scelta rapida per la selezione di schede adiacenti

Premere CTRL+TAB per selezionare il controllo TabViewItem successivo. Premere CTRL+MAIUSC+TAB per selezionare l'elemento TabViewItem precedente. A questo scopo, l'elenco di tab è "ad anello", quindi selezionando la scheda successiva mentre è selezionata l'ultima scheda, verrà selezionata la prima scheda.

Chiusura di una scheda

Premere CTRL+F4 per generare l'evento TabCloseRequested . Gestisci l'evento e chiudi la scheda, se opportuno.

Suggerimento

Per altre informazioni, vedere Indicazioni sulla tastiera per gli sviluppatori più avanti in questo articolo.

Creare una visualizzazione a schede

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

Gli esempi in questa sezione illustrano diversi modi per configurare un controllo TabView .

Elementi delle schede

Ogni scheda in un controllo TabView è rappresentata da un controllo TabViewItem , che include sia la scheda visualizzata nella striscia di schede che il contenuto mostrato sotto la striscia di schede.

Configurare una scheda

Per ogni elemento TabViewItem, è possibile impostare un'intestazione e un'icona e specificare se l'utente può chiudere la scheda.

  • La proprietà Header viene in genere impostata su un valore stringa che fornisce un'etichetta descrittiva per la scheda. Tuttavia, la Header proprietà può essere qualsiasi oggetto. È anche possibile utilizzare la proprietà HeaderTemplate per specificare un DataTemplate che definisce la modalità di visualizzazione dei dati di intestazione associati.
  • Impostare la proprietà IconSource per specificare un'icona per la scheda.
  • Per impostazione predefinita, la scheda mostra un pulsante di chiusura (X). Puoi impostare la proprietà IsClosable su false per nascondere il pulsante di chiusura e assicurarti che un utente non possa chiudere la scheda. Se chiudi le schede nel codice dell'app all'esterno di un evento richiesto di chiusura , devi prima verificare che IsClosable sia true.)

Per TabView, è possibile configurare diverse opzioni applicabili a tutte le schede.

  • Per impostazione predefinita, il pulsante di chiusura è sempre visibile per le schede chiudibili. È possibile impostare la proprietà CloseButtonOverlayMode su OnPointerOver per modificare questo comportamento. In questo caso, la scheda selezionata mostra sempre il pulsante di chiusura se è bloccabile, ma le schede non selezionate mostrano il pulsante di chiusura solo quando la scheda è bloccabile e l'utente ha il puntatore su di esso.
  • È possibile impostare la proprietà TabWidthMode per modificare le dimensioni delle schede. La Width proprietà viene ignorata in TabViewItem.) Queste sono le opzioni nell'enumerazione TabViewWidthMode :
    • Equal - Ogni scheda ha la stessa larghezza. Si tratta dell'impostazione predefinita.
    • SizeToContent - Ogni scheda regola la larghezza del contenuto all'interno della scheda.
    • Compact - Le schede non selezionate vengono ridotte per visualizzare solo l'icona. La scheda selezionata viene modificata per visualizzare il contenuto all'interno della scheda.

Contenuto

Gli elementi visualizzati nella scheda selezionata vengono aggiunti alla proprietà Content di TabViewItem. TabViewItem è un ContentControl, quindi è possibile aggiungere qualsiasi tipo di oggetto come contenuto. È anche possibile applicare un DataTemplate alla proprietà ContentTemplate. Per altre informazioni, vedere la classe ContentControl .

Gli esempi in questo articolo illustrano un semplice caso di aggiunta di testo direttamente all'elemento Content in XAML. Tuttavia, l'interfaccia utente reale è in genere più complessa. Un modo comune per aggiungere un'interfaccia utente complessa come contenuto di una scheda consiste nell'incapsularlo in un oggetto UserControl o in una pagina e aggiungerlo come contenuto di TabViewItem. In questo esempio si presuppone che l'app abbia un oggetto UserControl XAML denominato PictureSettingsControl.

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

Schede statiche

In questo esempio viene mostrato un TabView semplice con due schede statiche. Entrambi gli elementi di tabulazioni vengono aggiunti in XAML come contenuto di TabView.

Per rendere statico un controllo TabView, usare queste impostazioni:

  • Impostare la proprietà IsAddTabButtonVisible su false per nascondere il pulsante aggiungi scheda e impedire la generazione dell'evento AddTabButtonClick .
  • Impostare la proprietà CanReorderTabs su false per impedire all'utente di trascinare le schede in un ordine diverso.
  • In ogni TabViewItem, impostare la proprietà IsClosable su false, così da nascondere il pulsante di chiusura scheda e impedire all'utente di generare l'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>

Schede documenti

Per impostazione predefinita, TabView è configurato per le schede dei documenti. L'utente può aggiungere nuove schede, riorganizzare le schede e chiudere le schede. In questa configurazione è necessario gestire gli eventi AddTabButtonClick e TabCloseRequested per abilitare la funzionalità.

Quando vengono aggiunte schede a un TabView, potrebbe arrivare un momento in cui ci sono troppe schede da visualizzare nella barra delle schede. In questo caso, verranno visualizzate le guide di scorrimento che consentono all'utente di scorrere la barra delle schede a sinistra e a destra per accedere alle schede nascoste.

In questo esempio viene creato un controllo TabView semplice con gestori eventi per supportare l'apertura e la chiusura delle schede. Il TabView_AddTabButtonClick gestore eventi mostra come aggiungere un oggetto TabViewItem nel codice.

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

Chiudere la finestra quando l'ultima scheda viene chiusa

Se tutte le schede dell'app sono chiudibili e la finestra dell'app deve essere chiusa quando l'ultima scheda viene chiusa, è necessario chiudere anche la finestra nel gestore eventi TabCloseRequested .

Innanzitutto, nel App.xaml.cs file aggiungere una public static proprietà che consentirà di accedere all'istanza Window da Page che ospita tabview. Vedere Migrazione dell'interfaccia utente.

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

    // Add this.
    public static Window Window { get { return m_window; } }
    // Update this to make it static.
    private static Window m_window;
}

Modificare quindi il gestore eventi TabCloseRequested per chiamare Window.Close se tutte le schede sono state rimosse da 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)
    {
        App.Window.Close();
    }
}

Nota

Questo esempio funziona per un'app con una singola finestra (MainWindow). Se la tua app ha più finestre o hai abilitato il distacco delle schede, devi tenere traccia di queste finestre e poi trovare quella corretta da chiudere. Per un esempio, vedere la sezione successiva.

Tabulazione

Tab tear-out descrive cosa accade quando un utente trascina una scheda dalla striscia di tabulazione di TabView e la sposta in un altro controllo TabView, in genere in una nuova finestra.

A partire da Windows App SDK 1.6, TabView ha una proprietà CanTearOutTabs che è possibile impostare per offrire un'esperienza avanzata per il trascinamento delle schede in una nuova finestra. Quando un utente trascina una scheda fuori dalla striscia di tabulazione con questa opzione è abilitata, viene creata immediatamente una nuova finestra durante il trascinamento, consentendo all'utente di trascinarla 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.

Quando si imposta la proprietà CanTearOutTabs su true, gli eventi di estrazione delle schede vengono attivati anziché gli eventi di trascina e rilascia. Per implementare l'estrazione delle schede, è necessario gestire questi eventi:

  • TabTearOutWindowRequested

    Questo evento si verifica quando una scheda viene prima trascinata fuori dalla barra delle schede. Gestiscilo per creare una nuova finestra e TabView in cui verrà spostata la scheda.

  • TabTearOutRequested

    Questo evento si verifica dopo che è stata fornita una nuova finestra. Gestisci il trasferimento della scheda rimossa dal TabView originale a un TabView nella nuova finestra.

  • EsternoStrappatoSchedeEliminazione

    Questo evento si verifica quando viene trascinata una scheda staccata su un TabView esistente. Gestisci il tab nel TabView che riceve il tab staccato per indicare se deve essere accettato.

  • ExternalStrappatoSchedeEliminate

    Questo evento si verifica quando una scheda strappata viene trascinata su un controllo TabView esistente e l'evento ExternalTornOutTabsDropping ha indicato che il rilascio è consentito. Gestisci nel TabView che riceve la scheda strappata per rimuovere la scheda dal TabView di origine e inserirla nel TabView ricevente all'indice specificato.

Questi eventi non vengono generati quando tab tear-out è abilitato: TabDragStarting, TabStripDragOver, TabStripDrop, TabDragCompleted, TabDroppedOutside.

Attenzione

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

Gli esempi seguenti mostrano come implementare i gestori di eventi per supportare la separazione di tab.

Configurare TabView

Questo codice XAML imposta la proprietà CanTearOutTabs su true e imposta i gestori eventi di tabulazione.

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

Creare e tenere traccia di una nuova finestra

Il trascinamento delle schede richiede la creazione e la gestione di nuove finestre nella tua applicazione.

Suggerimento

L'app Raccolta WinUI include una WindowHelper classe che semplifica la gestione delle finestre nell'app. È possibile copiarlo da GitHub nel repository della raccolta WinUI: WindowHelper.cs. Consigliamo di utilizzare questa classe helper per implementare l'estrazione delle schede. Vedere TabViewWindowingSamplePage su GitHub per capire come viene utilizzata.

In questo articolo i metodi helper vengono copiati da WindowHelper.cs, ma vengono modificati e visualizzati inline per la leggibilità.

In questo caso viene creato un elenco per tenere traccia di tutte le finestre attive in App.xaml.cs. Il OnLaunched metodo viene aggiornato per tenere traccia della finestra dopo la creazione. Questa operazione non è necessaria se si usa la WindowHelper classe .

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 inizia l'estrazione della scheda, viene richiesta una nuova finestra. In questo caso, la variabile tabTearOutWindow fornisce l'accesso alla nuova finestra dopo la creazione. I metodi helper CreateWindow e TrackWindow creano una nuova finestra e la aggiungono all'elenco di rilevamento delle finestre attive.

Dopo aver creato la nuova finestra, è necessario creare una nuova pagina e impostarla come contenuto della finestra. La nuova pagina deve contenere un controllo TabView in cui verrà spostata la scheda disastrata nel TabTearOutRequested gestore eventi.

Suggerimento

In questo esempio viene creata una nuova MainPage classe, poiché contiene solo un controllo TabView vuoto (nessuna scheda viene aggiunta direttamente in XAML). Se MainPage include altri elementi dell'interfaccia utente che non devono essere visualizzati nella finestra di separazione, è possibile creare una pagina separata che includa solo gli elementi necessari (incluso almeno un controllo TabView) e creare un'istanza di tale pagina.

Assegnare infine il AppWindow.Id della nuova finestra alla args. proprietà NewWindowId. Questo verrà usato nella proprietà TabViewTabTearOutRequestedEventArgs.NewWindowId in modo da poter accedere alla finestra da tale gestore eventi.

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

Chiudere una finestra quando l'ultima scheda viene chiusa

Come accennato in precedenza, potresti voler chiudere la finestra quando l'ultima scheda di TabView è chiusa. Se l'app ha più finestre, devi trovare la finestra corretta per chiudere l'elenco delle finestre rilevate. In questo esempio viene illustrato come eseguire questa operazione.

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

Muovi la scheda nella nuova finestra

Dopo aver fornito la nuova finestra, è necessario rimuovere la scheda strappata da sender TabView e aggiungerla a TabView nella nuova finestra. In questo esempio, il metodo di supporto public AddTabToTabs consente di accedere alla TabView nella nuova istanza MainPage dall'istanza originale della pagina per aggiungere la scheda staccata.

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

Trascinare una scheda staccata su un'altra TabView

Quando una scheda è stata estratta e inserita in una nuova finestra, come illustrato nei passaggi precedenti, una delle due cose può verificarsi:

  • L'utente può trascinare la scheda e questa rimane aperta nella nuova finestra. Il processo di disinstallazione termina qui e non vengono generati altri eventi.
  • L'utente può continuare a trascinare la scheda staccata su un controllo TabView esistente. In questo caso, il processo continua e vengono generati diversi altri eventi per permettere di rimuovere la scheda dal TabView originale e inserire la scheda esterna in un TabView esistente.

Quando la scheda viene trascinata sull'oggetto TabView esistente, l'evento ExternalTornOutTabsDropping viene generato. Nel gestore eventi è possibile determinare se l'inserimento della scheda in questo TabView è consentito. Nella maggior parte dei casi, è sufficiente impostare la args. proprietà AllowDrop su true. Tuttavia, se è necessario eseguire eventuali controlli prima di impostare tale proprietà, è possibile farlo qui. Se AllowDrop è impostato su false, l'azione di trascinamento della scheda continua e l'evento ExternalTornOutTabsDropped non viene generato.

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

Se AllowDrop è impostato su true nel ExternalTornOutTabsDropping gestore eventi, l'evento ExternalTornOutTabsDropped viene generato immediatamente.

Nota

Il Dropped nel nome dell'evento non corrisponde direttamente all'idea di un'azione di rilascio nelle API di trascinamento della selezione. In questo caso, l'utente non deve lasciare il tab per eseguire un'operazione di drop. L'evento viene generato mentre la scheda viene sostenuta sopra la striscia di tabulazioni e il codice viene eseguito per rilasciare la scheda in TabView.

Il gestore dell'evento ExternalTornOutTabsDropped segue lo stesso modello dell'evento TabTearOutRequested , ma invertito; è necessario rimuovere la scheda da TabView di origine e inserirla in sender TabView.

sender TabView è il controllo in cui viene inserita la scheda, quindi usiamo il GetParentTabView metodo helper per trovare la scheda di origine. Inizia con l'elemento TabViewItem espulso e usa VisualTreeHelper per risalire la struttura ad albero visuale e trovare il TabView a cui appartiene l'elemento. Dopo aver trovato TabView, l'oggetto TabViewItem viene rimosso dall'insieme TabItems e inserito nell'insieme senderTabItems TabView in corrispondenza dell'indice specificato da args.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;
}

Suggerimento

Se usi Windows Community Toolkit, puoi usare il FindAscendant metodo helper nel toolkit DependencyObjectExtensions anziché GetParentTabView.

Visualizzare le schede TabView nella barra del titolo di una finestra

Invece di far sì che le schede occupino una propria riga sotto la barra del titolo di una finestra, è possibile combinare le due aree nella stessa zona. In questo modo puoi risparmiare spazio verticale per il contenuto e conferire all'app un aspetto più moderno.

Poiché un utente può trascinare una finestra dalla relativa barra del titolo per riposizionare la finestra, è importante che la barra del titolo non sia completamente piena di schede. Pertanto, quando si visualizzano schede in una barra del titolo, è necessario specificare una parte della barra del titolo da riservare come area trascinabile. Se non si specifica un'area trascinabile, l'intera barra del titolo sarà trascinabile, impedendo così alle schede di ricevere eventi di input. Se il controllo TabView verrà visualizzato nella barra del titolo di una finestra, dovresti sempre includere TabStripFooter nel tuo TabView e designarlo come regione trascinabile.

Per altre informazioni, vedi Personalizzazione della barra del titolo

Schede nella barra del titolo

<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)
{
    App.Window.ExtendsContentIntoTitleBar = true;
    App.Window.SetTitleBar(CustomDragRegion);
    CustomDragRegion.MinWidth = 188;
}

Nota

La modalità di recupero di un riferimento alla finestra può variare a seconda della modalità di rilevamento delle finestre nell'app. Per altre informazioni, vedere Chiudere la finestra quando l'ultima scheda viene chiusae Creare e tenere traccia di una nuova finestra in questo articolo.

Linee guida per la tastiera per gli sviluppatori

Suggerimento

Per altre informazioni sul supporto della tastiera predefinito, vedere Spostamento tramite tastiera in precedenza in questo articolo.

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. In genere questa scheda viene popolata con un documento predefinito oppure viene creata vuota con un modo semplice per sceglierne il 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.
  • Ctrl + MAIUSC + T dovrebbe aprire le schede chiuse di recente (o più accuratamente, aprire nuove schede con lo stesso contenuto delle schede 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.
  • Ctrl + 1 deve selezionare la prima scheda nell'elenco delle 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.
  • Ctrl + 9 deve selezionare l'ultima scheda nell'elenco delle 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, questo esempio implementa CTRL+ T, CTRL + W, CTRL + 1-8 e 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 is not 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;
    if (tab is not null)
    {
        CloseSelectedTab(tabView, tab);
    }
    args.Handled = true;
}

private void TabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
{
    CloseSelectedTab(sender, args.Tab);
}

private void CloseSelectedTab(TabView tabView, TabViewItem tab)
{
    // Only remove the selected tab if it can be closed.
    if (tab.IsClosable == true)
    {
        tabView.TabItems.Remove(tab);
    }
}


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

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

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

Il controllo TabView per le app UWP è incluso nell'ambito di WinUI 2. Per maggiori informazioni, incluse le istruzioni per l'installazione, vedere WinUI 2. Le API per questo controllo esistono nello spazio dei nomi Microsoft.UI.Xaml.Controls.

Le API di strappo tab non sono incluse nella versione WinUI 2 di TabView.

È consigliabile usare la versione più recente di WinUI 2 per ottenere gli stili, i modelli e le funzionalità più recenti per tutti i controlli. WinUI 2.2 o versione successiva include un nuovo modello per questo controllo che usa angoli arrotondati. Per altre informazioni, vedere Raggio dell'angolo.

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

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

<muxc:TabView />