Udostępnij przez


Widok zakładek

Kontrolka TabView to narzędzie do wyświetlania zestawu kart i odpowiedniej zawartości. Kontrolki TabView są przydatne do wyświetlania kilku stron (lub dokumentów) zawartości, umożliwiając użytkownikowi zmienianie, zamykanie lub otwieranie nowych kart.

Przykład widoku TabView

Czy jest to właściwa kontrola?

Ogólnie rzecz biorąc, interfejsy użytkownika z kartami są dostępne w jednym z dwóch odrębnych stylów, które różnią się funkcją i wyglądem:

  • Karty statyczne to karty często spotykane w oknach ustawień. Zawierają one zestaw stron w stałej kolejności, która zwykle zawiera wstępnie zdefiniowaną zawartość.
  • Karty dokumentu są rodzajem kart spotykanych w przeglądarkach, takich jak Microsoft Edge. Użytkownicy mogą tworzyć, usuwać i rozmieszczać karty, przenosić karty między oknami oraz zmieniać zawartość kart.

Domyślnie funkcja TabView jest skonfigurowana do udostępniania kart dokumentów. Zalecamy korzystanie z widoku TabView, gdy użytkownicy będą mogli wykonywać następujące działania:

  • Dynamicznie otwieraj, zamykaj lub przestawiaj karty.
  • Otwórz dokumenty lub strony internetowe bezpośrednio w kartach.
  • Przeciągnij i upuść karty między oknami.

Interfejs API TabView pozwala na konfigurowanie kontrolki dla kart statycznych. Jednak aby postępować zgodnie ze wskazówkami dotyczącymi projektowania systemu Windows i jeśli istnieje więcej niż kilka statycznych elementów nawigacji, rozważ użycie kontrolki NavigationView .

Anatomia

Interfejs użytkownika z kartami jest tworzony za pomocą kontrolki TabView i co najmniej jednej kontrolki TabViewItem. TabView hostuje wystąpienia TabViewItem, które reprezentują pojedynczą kartę i jej zawartość.

Części elementu TabView

Ten obraz przedstawia części kontrolki TabView . Pasek tabulatora ma nagłówek i stopkę, ale w przeciwieństwie do dokumentu nagłówek i stopka paska tabulatora znajdują się odpowiednio po lewej i prawej stronie paska.

Na tym obrazie przedstawiono części kontrolki widoku zakładek. Pasek zakładek zawiera cztery karty, a jego nagłówek i stopka znajdują się odpowiednio na lewym i prawym krańcu pasa.

Elementy TabViewItem

Ten obraz przedstawia części kontrolki TabViewItem . Chociaż zawartość jest wyświetlana wewnątrz kontrolki TabView, zawartość jest w rzeczywistości częścią elementu TabViewItem.

Na tym obrazie przedstawiono części kontrolki elementu widoku karty. Wybrana jest pojedyncza karta z ikoną i etykietą z obszarem zawartości poniżej karty.

Rekomendacje

Wybór karty

Większość użytkowników korzysta z kart dokumentów po prostu za pomocą przeglądarki internetowej. Gdy używają kart dokumentów w twojej aplikacji, ich doświadczenia wpływają na oczekiwania dotyczące zachowania kart.

Niezależnie od tego, jak użytkownik wchodzi w interakcję z zestawem kart dokumentów, zawsze powinna istnieć aktywna karta. Jeśli użytkownik zamknie wybraną kartę lub przeniesie ją do innego okna, inna karta powinna stać się aktywną kartą. TabView spróbuje to zrobić, automatycznie wybierając następną kartę. Jeśli masz dobry powód, dla którego aplikacja powinna zezwalać na korzystanie z TabView bez zaznaczonej karty, obszar zawartości TabView będzie po prostu pusty.

Nawigacja za pomocą klawiatury

TabView domyślnie obsługuje wiele typowych scenariuszy nawigacji za pomocą klawiatury. W tej sekcji opisano wbudowane funkcje i przedstawiono zalecenia dotyczące dodatkowych funkcji, które mogą być przydatne w przypadku niektórych aplikacji.

Zachowanie tabulatora i kursora

Gdy fokus przechodzi do obszaru TabStrip, zaznaczona TabViewItem zyskuje fokus. Następnie użytkownik może używać strzałek w lewo i w prawo, aby przesunąć fokus (nie zaznaczenie) na inne karty na pasku kart. Fokus strzałki jest uwięziony wewnątrz paska tabulatora i przycisku dodaj kartę (+), jeśli istnieje. Aby przenieść fokus z obszaru paska tabulatora, użytkownik może nacisnąć Tab , co spowoduje przeniesienie fokusu do następnego elementu z możliwością koncentracji uwagi.

Przenieś fokus przez klawisz Tab

Przenieś fokus za pomocą klawisza Tab

Klawisze strzałek nie zmieniają skupienia

Klawisze strzałek nie przesuwają fokusa

Wybieranie karty

Gdy element TabViewItem ma fokus, naciśnij Spacja lub Enter , aby wybrać ten element TabViewItem.

Użyj strzałek, aby przenieść fokus, a następnie naciśnij Spacja , aby wybrać kartę.

Spacja do wybrania karty

Skróty do wybierania sąsiednich kart

Naciśnij Ctrl+Tab , aby wybrać następny element TabViewItem. Naciśnij Ctrl+Shift+Tab , aby wybrać poprzedni element TabViewItem. W tych celach lista kart jest "zapętlona", więc gdy wybrana jest ostatnia karta, wybranie następnej spowoduje wybranie pierwszej karty.

Zamknięcie karty

Naciśnij Ctrl + F4 , aby podnieść zdarzenie TabCloseRequested . Zajmij się zdarzeniem i zamknij kartę, jeśli to stosowne.

Wskazówka

Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące klawiatury dla deweloperów w dalszej części tego artykułu.

Utwórz widok karty

Aplikacja Galeria WinUI 3 zawiera interaktywne przykłady większości kontrolek, funkcji i funkcji interfejsu WinUI 3. Pobierz aplikację ze Sklepu Microsoft lub pobierz kod źródłowy w witrynie GitHub

W przykładach w tej sekcji przedstawiono różne sposoby konfigurowania kontrolki TabView .

Elementy widoku zakładki

Każda karta w widoku TabView jest reprezentowana przez kontrolkę TabViewItem , która zawiera zarówno kartę wyświetlaną na pasku karty, jak i zawartość pokazaną poniżej paska karty.

Skonfiguruj kartę

Dla każdego elementu TabViewItem można ustawić nagłówek i ikonę oraz określić, czy użytkownik może zamknąć kartę.

  • Właściwość Nagłówek jest zwykle ustawiana na wartość ciągu, która zawiera opisową etykietę dla karty. Header Jednak właściwość może być dowolnym obiektem. Można również użyć właściwości HeaderTemplate , aby określić element DataTemplate definiujący sposób wyświetlania danych nagłówka powiązanego.
  • Ustaw właściwość IconSource, aby ustawić ikonę dla karty.
  • Domyślnie na karcie jest wyświetlany przycisk zamknięcia (X). Możesz ustawić właściwość IsClosable , aby false ukryć przycisk zamknięcia i upewnić się, że użytkownik nie może zamknąć karty. (Jeśli zamkniesz karty w kodzie aplikacji poza żądanym zdarzeniem zamknięcia , najpierw sprawdź, czy jest to IsClosabletrue.

W przypadku widoku TabView można skonfigurować kilka opcji, które mają zastosowanie do wszystkich kart.

  • Domyślnie przycisk zamknięcia jest zawsze wyświetlany dla kart z możliwością zamknięcia. Możesz ustawić właściwość CloseButtonOverlayMode na OnPointerOver, aby zmienić to zachowanie. W takim przypadku wybrana karta zawsze wyświetla przycisk zamknięcia, jeśli można ją zamknąć, ale niezaznaczone karty pokazują przycisk zamknięcia tylko wtedy, gdy można je zamknąć i użytkownik ma nad nim kursor.
  • Możesz ustawić właściwość TabWidthMode, aby zmienić sposób ustalania rozmiaru kart. (Właściwość Width jest ignorowana dla TabViewItem.) Są to opcje wyliczenia TabViewWidthMode:
    • Equal — Każda zakładka ma taką samą szerokość. Jest to opcja domyślna.
    • SizeToContent - Każda karta dostosowuje szerokość do zawartości na karcie.
    • Compact - Niezaznaczone karty zwiń, aby wyświetlić tylko ich ikonę. Wybrana karta dostosowuje się do wyświetlania zawartości na karcie.

Content

Elementy wyświetlane na wybranej karcie są dodawane do właściwości Content elementu TabViewItem. TabViewItem jest elementem ContentControl, dzięki czemu można dodać dowolny typ obiektu jako zawartość. Można również zastosować element DataTemplate do właściwości ContentTemplate . Aby uzyskać więcej informacji, zobacz klasę ContentControl .

Przykłady w tym artykule pokazują prosty przypadek dodawania tekstu bezpośrednio do Content elementu w języku XAML. Jednak rzeczywisty interfejs użytkownika jest zazwyczaj bardziej złożony. Typowym sposobem dodawania złożonego interfejsu użytkownika jako zawartości karty jest opakowanie go w kontrolce UserControl lub na Page i dodanie go jako zawartość elementu TabViewItem. W tym przykładzie założono, że aplikacja ma element UserControl XAML o nazwie PictureSettingsControl.

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

Karty statyczne

W tym przykładzie przedstawiono prosty widok TabView z dwiema kartami statycznymi. Oba zakładki są dodawane w XAML jako zawartość TabView.

Aby utworzyć statyczny element TabView, użyj następujących ustawień:

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

Karty dokumentu

Domyślnie widok TabView jest skonfigurowany dla kart dokumentów. Użytkownik może dodawać nowe karty, rozmieszczać karty i zamykać karty. W tej konfiguracji należy obsługiwać zdarzenia AddTabButtonClick i TabCloseRequested w celu włączenia funkcji.

Po dodaniu kart do widoku TabView może być w końcu zbyt wiele kart do wyświetlenia na pasku tabulacji. W takim przypadku pojawią się wypustki przewijania, które pozwolą użytkownikowi przewijać pasek tabulacji w lewo i w prawo, aby uzyskać dostęp do ukrytych kart.

W tym przykładzie tworzona jest prosta TabView wraz z procedurami obsługi zdarzeń, które umożliwiają otwieranie i zamykanie kart. Procedura TabView_AddTabButtonClick obsługi zdarzeń pokazuje, jak dodać element TabViewItem w kodzie.

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

Zamknij okno w momencie zamknięcia ostatniej karty

Jeśli w aplikacji wszystkie zakładki mogą być zamykane, a okno aplikacji powinno zamknąć się po zamknięciu ostatniej zakładki, należy również zamknąć okno w obsłudze zdarzenia TabCloseRequested.

Najpierw w App.xaml.cs pliku dodaj public static właściwość, która pozwoli uzyskać dostęp do Window wystąpienia z Page obiektu hostującego TabView. (Zobacz Śledzenie bieżącego okna w przeglądzie okien).

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

Następnie zmodyfikuj procedurę obsługi zdarzeń TabCloseRequested , aby wywołać metodę Window.Close , jeśli wszystkie karty zostały usunięte z elementu 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();
    }
}

Uwaga / Notatka

Ten przykład działa w przypadku aplikacji z jednym oknem (MainWindow). Jeśli aplikacja ma wiele okien lub włączono odrywanie kart, musisz monitorować okna, a następnie znaleźć właściwe, aby je zamknąć. Zobacz następną sekcję, aby zapoznać się z przykładem tego.

Odrywalne zakładki

Oderwanie karty opisuje, co się dzieje, gdy użytkownik przeciąga kartę z paska kart TabView i przenosi ją do innej kontrolki TabView, zazwyczaj w nowym oknie.

Rozpoczynając od Windows App SDK 1.6, kontrolka TabView ma właściwość CanTearOutTabs, którą można ustawić, aby umożliwić lepsze przeciąganie kart do nowego okna. Gdy użytkownik przeciąga kartę z paska tabulatora przy włączonej tej opcji, nowe okno jest natychmiast tworzone podczas przeciągania, co pozwala użytkownikowi przeciągnąć je na krawędź ekranu, aby zmaksymalizować lub przyciągnąć okno w jednym płynnym ruchu. Ta implementacja nie korzysta również z interfejsów API przeciągania i upuszczania, dzięki czemu nie jest narażona na żadne ograniczenia tych interfejsów API.

Po ustawieniu właściwości CanTearOutTabs na true, zgłaszane są zdarzenia wyrywania kart zamiast zdarzeń przeciągania i upuszczania. Aby zaimplementować wyrwanie karty, należy obsługiwać następujące zdarzenia:

  • TabTearOutWindowRequested

    To zdarzenie występuje, gdy karta jest najpierw przeciągnięta z paska tabulatora. Zajmij się nim, aby utworzyć nowe okno i widok TabView, do którego zostanie przeniesiona karta.

  • TabTearOutRequested

    To zdarzenie występuje po udostępnieniu nowego okna. Obsłuż ją, aby przenieść rozdartą kartę z elementu TabView pochodzącego z widoku TabView do widoku TabView w nowym oknie.

  • ExternalTornOutTabsDropping

    To zdarzenie występuje, gdy oderwana karta jest przeciągnięta na istniejący widżet TabView. Obsłuż go w widoku TabView, który otrzymuje rozdartą kartę, aby wskazać, czy karta powinna zostać zaakceptowana.

  • ExternalTornOutTabsDropped

    To zdarzenie występuje, gdy wysunięta karta jest przeciągnięta nad istniejące okno TabView, a ExternalTornOutTabsDropping zdarzenie wskazuje, że upuszczenie jest dozwolone. Obsłuż go w widoku TabView, który otrzymuje rozdartą kartę, aby usunąć kartę z obiektu TabView pochodzącego z elementu TabView i wstawić go do odbierającego widoku TabView w określonym indeksie.

Te zdarzenia nie są zgłaszane, gdy włączono funkcję wyrywania karty: TabDragStarting, TabStripDragOver, TabStripDrop, TabDragCompleted, TabDroppedOutside.

Ostrzeżenie

Funkcja odrywania zakładki jest obsługiwana w procesach uruchamianych z podwyższonymi uprawnieniami jako Administrator.

W poniższych przykładach pokazano, jak zaimplementować programy obsługi zdarzeń w celu obsługi usuwania kart.

Konfigurowanie widoku TabView

Ten kod XAML ustawia właściwość CanTearOutTabs na true i konfiguruje procedury obsługi zdarzeń usuwania tabulacji.

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

Tworzenie i śledzenie nowego okna

Wyrwanie karty wymaga utworzenia nowych okien w aplikacji i zarządzania nimi.

Wskazówka

Aplikacja z galerii WinUI zawiera klasę WindowHelper , która ułatwia zarządzanie oknami w aplikacji. Możesz skopiować go z usługi GitHub w repozytorium Galerii WinUI: WindowHelper.cs. Zalecamy, aby ta klasa pomocnika implementować wyrwanie kart. Zobacz element TabViewWindowingSamplePage w witrynie GitHub, aby zobaczyć, jak jest używany.

W tym artykule metody pomocnicze są kopiowane z WindowHelper.cs, ale są zmodyfikowane i pokazane bezpośrednio w tekście dla większej czytelności.

W tym miejscu zostanie utworzona lista śledzenia wszystkich aktywnych okien w programie App.xaml.cs. Metoda OnLaunched jest aktualizowana w celu śledzenia okna po jego utworzeniu. (Nie jest to konieczne, jeśli używasz WindowHelper klasy).

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

Po rozpoczęciu wyrywania karty jest wymagane nowe okno. W tym miejscu zmienna tabTearOutWindow zapewnia dostęp do nowego okna po jego utworzeniu. Metody pomocnicze CreateWindow i TrackWindow tworzą nowe okno i dodają je do listy śledzenia aktywnych okien.

Po utworzeniu nowego okna należy utworzyć nową stronę i ustawić ją jako zawartość okna. Nowa strona musi zawierać kontrolkę TabView, do której zostanie przeniesiona karta rozdarta w programie obsługi zdarzeń TabTearOutRequested .

Wskazówka

W tym przykładzie utworzymy nową MainPage klasę, ponieważ zawiera ona tylko pusty widok TabView (żadne karty nie są dodawane bezpośrednio w języku XAML). Jeśli MainPage zawiera inne elementy interfejsu użytkownika, które nie powinny być wyświetlane w rozdartym oknie, możesz utworzyć oddzielną stronę zawierającą tylko wymagane elementy (w tym co najmniej element TabView) i utworzyć wystąpienie tej strony.

Na koniec przypisz AppWindow.Id nowego okna do args. właściwości NewWindowId. Będzie to używane we właściwości TabViewTabTearOutRequestedEventArgs.NewWindowId , aby można było uzyskać dostęp do okna z poziomu tej procedury obsługi zdarzeń.

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

Zamknij okno po zamknięciu ostatniej karty

Jak wspomniano wcześniej, możesz chcieć zamknąć okno po zamknięciu ostatniej karty w widoku TabView. Jeśli aplikacja ma wiele okien, musisz znaleźć odpowiednie okno, aby zamknąć je na liście śledzonych okien. W tym przykładzie pokazano, jak to zrobić.

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

Przenieś kartę do nowego okna

Po udostępnieniu nowego okna, należy usunąć wyrwaną kartę z TabView i dodać ją do TabView w nowym oknie. W tym przykładzie, funkcja pomocnicza public AddTabToTabs umożliwia dostęp do widoku zakładek TabView w nowym MainPage wystąpieniu z oryginalnego wystąpienia strony w celu dodania do niej wyciągniętej zakładki.

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

Przeciągnij rozdartą kartę na inny element TabView

Gdy karta została rozdarta i umieszczona w nowym oknie, jak pokazano w poprzednich krokach, jedna z dwóch rzeczy może się zdarzyć:

  • Użytkownik może usunąć kartę i pozostaje w nowym oknie. Proces wyrywania kończy się tutaj i nie są już wywoływane żadne zdarzenia.
  • Użytkownik może nadal przeciągać wydzieloną zakładkę z powrotem na istniejącą kontrolkę TabView. W takim przypadku proces będzie kontynuowany i zostanie zgłoszonych kilka kolejnych zdarzeń, aby umożliwić usunięcie karty z oryginalnego widoku TabView i wstawienie karty zewnętrznej do istniejącego widoku TabView.

Gdy karta zostanie przeciągnięta przez istniejący element TabView, zostanie zgłoszone zdarzenie ExternalTornOutTabsDropping. W obsłudze zdarzenia można określić, czy wstawianie karty do tego widoku TabView jest dozwolone. W większości przypadków wystarczy ustawić tę właściwość args. na . Jeśli jednak musisz wykonać jakiekolwiek kontrole przed ustawieniem tej właściwości, możesz to zrobić tutaj. Jeśli AllowDrop zostanie ustawione na false, akcja przeciągania tabulatora będzie kontynuowana, a zdarzenie ExternalTornOutTabsDropped nie zostanie zgłoszone.

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

Jeśli AllowDrop jest ustawiona na wartość true w procedurze obsługi zdarzenia ExternalTornOutTabsDropping, zdarzenie ExternalTornOutTabsDropped jest natychmiast zgłaszane.

Uwaga / Notatka

Nazwa Dropped zdarzenia nie odpowiada bezpośrednio idei akcji upuść w API przeciągania i upuszczania. W tym miejscu użytkownik nie musi zwalniać zakładki, aby wykonać akcję przeciągnięcia i upuszczenia. Zdarzenie jest wywoływane, gdy karta jest przeciągana nad paskiem kart, a kod jest wykonywany w celu upuszczenia karty do widoku TabView.

Procedura obsługi zdarzeń ExternalTornOutTabsDropped jest zgodna z tym samym wzorcem co zdarzenie TabTearOutRequested, ale odwrócone; należy usunąć kartę z oryginalnego widoku TabView i wstawić ją do sender widoku TabView.

TabView to kontrolka sender , do którego jest wstawiana karta, dlatego używamy GetParentTabView metody pomocniczej do znalezienia karty źródłowej. Rozpoczyna się od rozdartego elementu TabViewItem i używa elementu VisualTreeHelper do chodzenia w drzewie wizualnym i znajdowania elementu TabView, do którego należy element. Po znalezieniu TabView, element TabViewItem zostaje usunięty z kolekcji TabItems i wstawiony do kolekcji TabView w miejscu określonym przez indeks senderTabItems.

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

Wskazówka

Jeśli używasz zestawu narzędzi Windows Community Toolkit, możesz użyć FindAscendant metody pomocniczej w module DependencyObjectExtensions zestawu narzędzi zamiast GetParentTabView.

Wyświetlanie kart TabView na pasku tytułu okna

Zamiast zakładek zajmujących własny wiersz poniżej paska tytułu okna, możesz scalić pasek tytułu i zakładki w jednym obszarze. Pozwala to zaoszczędzić miejsce na zawartość w pionie i zapewnia aplikacji nowoczesny wygląd.

Ważne jest, aby pasek tytułu nie był całkowicie wypełniony kartami, ponieważ użytkownik może przeciągnąć okno za jego pomocą, aby zmienić położenie okna. W związku z tym, wyświetlając karty na pasku tytułu, należy określić element paska tytułu, który ma być zarezerwowany do przeciągania. Jeśli nie określisz regionu przeciąganego, cały pasek tytułu będzie przeciągany, co uniemożliwia kartom odbieranie zdarzeń wejściowych. Jeśli element TabView będzie wyświetlany na pasku tytułu okna, zawsze należy umieścić TabStripFooter w TabView i oznaczyć go jako obszar przeciągania.

Aby uzyskać więcej informacji, zobacz dostosowywanie paska tytułu

Karty na pasku tytułu

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

Uwaga / Notatka

Sposób uzyskiwania odwołania do okna może się różnić w zależności od sposobu śledzenia okien w aplikacji. Aby uzyskać więcej informacji, zobacz Zamykanie okna po zamknięciu ostatniej kartyi Tworzenie i śledzenie nowego okna w tym artykule.

Wskazówki dotyczące klawiatury dla deweloperów

Wskazówka

Aby uzyskać więcej informacji na temat wbudowanej obsługi klawiatury, zobacz Nawigacja za pomocą klawiatury wcześniej w tym artykule.

Niektóre aplikacje mogą wymagać bardziej zaawansowanej kontrolki klawiatury. Rozważ zaimplementowanie następujących skrótów, jeśli są one odpowiednie dla twojej aplikacji.

Ostrzeżenie

Jeśli dodajesz TabView do istniejącej aplikacji, być może już utworzyłeś skróty klawiaturowe, które odpowiadają kombinacjom klawiszy zalecanych skrótów klawiaturowych dla TabView. W takim przypadku należy rozważyć, czy zachować istniejące skróty, czy też zaoferować intuicyjne środowisko tabulacji dla użytkownika.

  • Ctrl + T powinien otworzyć nową kartę. Zazwyczaj ta karta jest wypełniana wstępnie zdefiniowanym dokumentem lub jest tworzona pusta za pomocą prostego sposobu wybierania jego zawartości. Jeśli użytkownik musi wybrać zawartość nowej karty, rozważ skoncentrowanie danych wejściowych na kontrolce wyboru zawartości.
  • Ctrl + W powinien zamknąć zaznaczoną kartę. Pamiętaj, że kontrolka TabView automatycznie wybierze następną kartę.
  • Ctrl + Shift + T powinna otwierać ostatnio zamknięte karty (lub dokładniej, otwierać nowe karty z tą samą zawartością co ostatnio zamknięte karty). Zacznij od ostatnio zamkniętej karty i przesuń do tyłu za każdym razem, gdy jest wywoływany skrót. Należy pamiętać, że wymaga to utrzymania listy ostatnio zamkniętych kart.
  • Ctrl + 1 powinien zaznaczyć pierwszą kartę na liście kart. Podobnie ctrl + 2 powinien zaznaczyć drugą kartę, Ctrl + 3 powinien zaznaczyć trzecią i tak dalej za pomocą Ctrl + 8.
  • Ctrl + 9 powinien wybrać ostatnią kartę na liście kart, niezależnie od liczby kart na liście.
  • Jeśli karty oferują więcej niż tylko polecenie zamknięcia (takie jak duplikowanie lub przypinanie karty), użyj menu kontekstowego, aby wyświetlić wszystkie dostępne akcje dla karty.

Implementowanie zachowania klawiatury w stylu przeglądarki

W tym przykładzie zaimplementowaliśmy kilka powyższych zaleceń w TabView. W szczególności w tym przykładzie zaimplementowane są Ctrl + T, Ctrl + W, Ctrl + 1–8 i 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 i WinUI 2

Ważne

Informacje i przykłady w tym artykule są zoptymalizowane dla aplikacji korzystających z Windows App SDK oraz WinUI 3, ale generalnie mają zastosowanie także w aplikacjach UWP używających WinUI 2. Zobacz dokumentację interfejsu API platformy UWP, aby uzyskać informacje i przykłady dotyczące platformy.

Ta sekcja zawiera informacje potrzebne do używania kontrolki w aplikacji platformy UWP lub WinUI 2.

Kontrolka TabView dla aplikacji platformy UWP jest dołączana w ramach interfejsu WinUI 2. Aby uzyskać więcej informacji, w tym instrukcje dotyczące instalacji, zobacz WinUI 2. Interfejsy API dla tej kontrolki istnieją w przestrzeni nazw Microsoft.UI.Xaml.Controls .

API odrywania kart nie są dostępne w wersji WinUI 2 TabView.

Zalecamy użycie najnowszego interfejsu WinUI 2 , aby uzyskać najbardziej aktualne style, szablony i funkcje dla wszystkich kontrolek. Interfejs WinUI 2.2 lub nowszy zawiera nowy szablon dla tej kontrolki, który używa zaokrąglonych narożników. Aby uzyskać więcej informacji, zobacz Zaokrąglenie narożnika.

Aby użyć kodu z tego artykułu w WinUI 2, użyj aliasu w XAML (używamy muxc), aby reprezentować API Biblioteki Interfejsu Użytkownika Windows, które są uwzględnione w Twoim projekcie. Aby uzyskać więcej informacji, zobacz Wprowadzenie do interfejsu WinUI 2 .

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

<muxc:TabView />