Поделиться через


Вид вкладок

Элемент управления TabView позволяет отобразить набор вкладок и их содержимое. Элементы управления TabView полезны для отображения нескольких страниц (или документов) содержимого, позволяя пользователю переупорядочения, закрытия или открытия новых вкладок.

Пример элемента TabView

Выбор правильного элемента управления

Как правило, интерфейсы UIs с вкладками входят в один из двух различных стилей, которые отличаются в функции и внешнем виде:

  • Стандартные вкладки часто встречаются в окнах параметров. На них располагается набор страниц в фиксированном порядке, которые обычно содержат предопределенное содержимое.
  • Вкладки документов — это вкладки, которые можно увидеть в браузере, например Microsoft Edge. Пользователи могут создавать, удалять и переупорядочивать вкладки, перемещать вкладки между окнами, а также и изменять содержимое вкладок.

По умолчанию TabView настроены для предоставления вкладок документов. Мы рекомендуем TabView, когда пользователи смогут:

  • Динамически открывайте, закрывайте или переупорядочивайте вкладки.
  • Откройте документы или веб-страницы непосредственно на вкладках.
  • Перетащите вкладки между окнами.

API TabView позволяет настроить элемент управления для статических вкладок. Тем не менее, чтобы следовать инструкциям по проектированию Windows, и если существует несколько статических элементов навигации, рассмотрите возможность использования элемента управления NavigationView.

Структура

Пользовательский интерфейс tabbed создается с помощью элемента управления TabView и одного или нескольких элементов управления TabViewItem. TabView размещает экземпляры TabViewItem, представляющие одну вкладку и содержимое.

Части TabView

На этом рисунке показаны части элемента управления TabView. строка вкладок имеет шапку и подвал, но, в отличие от документа, они находятся на самой левой и самой правой сторонах строки соответственно.

На этом изображении показаны части элемента управления представлением вкладок. Полоса вкладок содержит четыре вкладки и имеет верхний и нижний колонтитул, расположенный в левом и крайнем правом углу полосы соответственно.

Компоненты TabViewItem

На этом рисунке показаны части элемента управления TabViewItem. Хотя содержимое отображается внутри элемента управления TabView, содержимое фактически является частью TabViewItem.

На этом изображении показаны части элемента управления элементом представления вкладок. Выбрана отдельная вкладка с значком и меткой с областью содержимого под вкладкой.

Рекомендации

Выбор вкладки

Большинство пользователей имеет опыт использования вкладок документов в веб-браузере. При использовании вкладок документов в приложении они исходят из имеющегося опыта использования вкладок.

Независимо от того, как пользователь взаимодействует с набором вкладок документов, всегда должна быть активная вкладка. Если пользователь закрывает выбранную вкладку или прерывает выбранную вкладку в другое окно, другая вкладка должна стать активной. TabView пытается сделать это автоматически, выбрав следующую вкладку. Если у вас есть хорошая причина, по которой приложение должно разрешить tabView с неизбранной вкладкой, область содержимого TabView будет просто пустой.

Навигация с помощью клавиатуры

TabView по умолчанию поддерживает многие распространенные сценарии навигации с помощью клавиатуры. В этом разделе описываются встроенные функции и приводятся рекомендации по дополнительным функциональным возможностям, которые могут быть полезны для некоторых приложений.

Поведение клавиши TAB и клавиш курсора

Когда фокус перемещается в область TabStrip, он переводится на выбранный элемент TabViewItem. Затем пользователь может использовать клавиши со стрелками влево и вправо для перемещения фокуса (не выделения) на другие вкладки в полосе вкладок. Фокус стрелки перемещается по полосе вкладок и кнопке добавления вкладки (+), если она есть. Чтобы переместить фокус из области полосы вкладок, пользователь может нажать клавишу TAB, которая переместит фокус на следующий фокусируемый элемент.

Переместить фокус с помощью клавиши Tab

Перемещение фокуса с помощью вкладки

клавиши стрелок не переключают фокус

клавиши стрелок не переключают фокус

Выбор вкладки

Когда TabViewItem имеет фокус, нажмите клавишу Пробел или Ввод, чтобы выбрать этот TabViewItem.

Использовать клавиши со стрелками для перемещения фокуса, а затем нажмите клавишу Пробел, чтобы выбрать вкладку.

пробел, чтобы выбрать вкладку

Сочетания клавиш для выбора соседних вкладок

Нажмите клавиши CTRL+TAB , чтобы выбрать следующий TabViewItem. Нажмите клавиши CTRL+SHIFT+TAB, чтобы выбрать предыдущий tabViewItem. В этих целях список вкладок "цикличен", поэтому выбор следующей вкладки при выборе последней вкладки приведет к тому, что первая вкладка будет выбрана.

Закрытие вкладки

Нажмите CTRL + F4, чтобы вызвать событие TabCloseRequested. Обработайте это событие и закройте вкладку, если это возможно.

Совет

Дополнительные сведения см. в руководстве по использованию клавиатуры для разработчиков позже в этой статье.

Создание представления вкладок

Приложение WinUI 3 Gallery включает интерактивные примеры для большинства элементов управления, функций и возможностей WinUI 3. Получите приложение из Microsoft Store или получите исходный код на GitHub

В примерах этого раздела показаны различные способы настройки элемента управления TabView.

Элементы представления вкладок

Каждая вкладка в TabView представлена элементом управления TabViewItem, который включает как вкладку, показанную в полосе вкладок, так и содержимое, показанное под полосой вкладок.

Настройка вкладки

Для каждого tabViewItem можно задать заголовок и значок и указать, может ли пользователь закрыть вкладку.

  • Свойство заголовка обычно имеет строковое значение, которое предоставляет описательную метку для вкладки. Однако свойство может быть любым объектом. Можно также использовать свойство HeaderTemplate, чтобы указать DataTemplate, которая определяет, как должны отображаться данные привязанного заголовка.
  • Задайте свойство IconSource, чтобы указать значок для вкладки.
  • По умолчанию на вкладке показана кнопка закрытия. Для свойства IsClosable можно задать значение false, чтобы убедиться, что пользователь не сможет закрыть вкладку.

Для TabView можно настроить несколько параметров, которые применяются ко всем вкладкам.

  • По умолчанию кнопка закрытия (X) всегда отображается для закрываемых вкладок. Чтобы изменить это поведение, можно задать для свойства CloseButtonOverlayMode значение OnPointerOver. В этом случае выбранная вкладка всегда показывает кнопку закрытия, если она может быть закрыта, но невыбранные вкладки показывают кнопку закрытия только если вкладка может быть закрыта и пользователь навёл указатель на нее.
  • Чтобы изменить размер вкладок, можно задать свойство TabWidthMode. (Свойство Width игнорируется в TabViewItem.) Это параметры перечисления TabViewWidthMode:
    • Equal . Каждая вкладка имеет одинаковую ширину. Это значение по умолчанию.
    • SizeToContent . Каждая вкладка настраивает ее ширину на содержимое на вкладке.
    • Compact — свернуть неизбранные вкладки, чтобы отобразить только значок. Выбранная вкладка настраивается для отображения содержимого на вкладке.

Содержание

Элементы, отображаемые на выбранной вкладке, добавляются в свойство Content элемента TabViewItem. TabViewItem — это ContentControl, поэтому можно добавить любой тип объекта в качестве содержимого. Вы также можете применить DataTemplate к свойству ContentTemplate. Смотрите класс ContentControl для получения дополнительной информации.

Примеры, приведенные в этой статье, показывают простой случай добавления текста непосредственно в элемент Content в XAML. Однако реальный пользовательский интерфейс обычно более сложный. Распространенный способ добавления сложного пользовательского интерфейса в качестве содержимого вкладки заключается в том, чтобы инкапсулировать его в UserControl или Pageи добавить это в качестве содержимого TabViewItem. В этом примере предполагается, что приложение имеет XAML UserControl с именем PictureSettingsControl.

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

Статические вкладки

В этом примере показан простой TabView с двумя статическими вкладками. Оба элемента вкладки добавляются в XAML в виде содержимого TabView.

Чтобы сделать TabView статическим, используйте следующие настройки:

  • Задайте свойств у IsAddTabButtonVisible, чтобы скрыть кнопку добавить вкладку и запретить вызов события addTabButtonClick.
  • Задайте для свойства CanReorderTabs значение , чтобы запретить пользователю перетаскивать вкладки в другой порядок.
  • На каждом TabViewItemзадайте для свойства IsClosable значение false, чтобы скрыть вкладку закрыть кнопку запретить пользователю вызывать событие 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>

Вкладки документов

По умолчанию TabView настраивается для вкладок документов . Пользователь может добавлять новые вкладки, изменять порядок вкладок и закрывать вкладки. В этой конфигурации необходимо обработать события AddTabButtonClick и TabCloseRequested для включения функциональности.

Когда вкладки добавляются в TabView, в конечном итоге может быть слишком много вкладок для отображения в полосе вкладок. В этом случае появятся полосы прокрутки, которые позволят пользователю получить доступ к скрытым вкладкам, прокручивая полосу вкладок влево и вправо.

В этом примере создается простой элемент TabView с обработчиками событий для реализации открытия и закрытия вкладок. Обработчик событий TabView_AddTabButtonClick показывает, как добавить TabViewItem в код.

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

Закройте окно при закрытии последней вкладки

Если все вкладки в приложении закрываются, и окно приложения должно закрыться при закрытии последней вкладки, необходимо также закрыть окно в обработчике событий TabCloseRequested.

Во-первых, в файле App.xaml.cs добавьте общедоступное свойство, которое позволит получить доступ к экземпляру Window из Page, на котором размещается TabView.

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

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

Затем измените обработчик событий TabCloseRequested, чтобы вызвать Window.Close, если все вкладки удалены из 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();
    }
}

Примечание.

Этот пример работает для приложения с одним окном (MainWindow). Если у вашего приложения несколько окон или вы включили открепление вкладок, необходимо отслеживать окна, а затем найти правильное окно для закрытия. Пример этого см. в следующем разделе.

Слеза вкладки

разрыв вкладки описывает, что происходит, когда пользователь перетаскивает вкладку из панели вкладок TabView и перемещает ее в другой элемент управления TabView, как правило, в новом окне.

Начиная с пакета SDK для приложений Windows 1.6, TabView имеет свойство CanTearOutTabs, которое можно настроить, чтобы обеспечить расширенный интерфейс для перетаскивания вкладок в новое окно. Когда пользователь перетаскивает вкладку из полосы вкладок с включенным параметром, новое окно сразу же создается во время перетаскивания, что позволяет пользователю перетаскивать его на край экрана, чтобы развернуть или привязать окно в одном плавном движении. Эта реализация также не использует API перетаскивания, поэтому это не влияет на какие-либо ограничения в этих API.

Если для свойства CanTearOutTabs задано значение , это приводит к возникновению событий отрыва вкладки вместо событий перетаскивания . Чтобы реализовать разрыв вкладки, необходимо обрабатывать следующие события:

  • Запрос на Вытеснение Вкладки в Отдельное Окно

    Это событие возникает, когда вкладка сначала перетаскивается из полосы вкладок. Управляйте процессом, чтобы создать новое окно и TabView, куда будет перемещена вкладка.

  • TabTearOutRequested

    Это событие возникает после предоставления нового окна. Используйте ее, чтобы переместить вырванную вкладку из исходного tabView в tabView в новом окне.

  • ExternalTornOutTabsDropping

    Это событие возникает, когда вырванная вкладка перетаскивается над существующим TabView. Обработайте это в TabView, который получает вырванную вкладку, для указания на то, следует ли принять вкладку.

  • ExternalTornOutTabsDropped

    Это событие возникает, когда вырванная вкладка перетаскивается по существующему TabView, а событие ExternalTornOutTabsDropping указывает, что сброс разрешён. Обработайте это в TabView, в который передаётся вырванная вкладка, чтобы удалить её из исходного TabView и вставить в получающий TabView по указанному индексу.

Эти события не возникают при включении разрыва вкладки: TabDragStarting, TabStripDragOver, TabStripDrop, TabDragCompleted, TabDroppedOutside.

Осторожность

Разрыв вкладок поддерживается в процессах, работающих с повышенными привилегиями от имени администратора.

В следующих примерах показано, как реализовать обработчики событий для поддержки разрыва вкладки.

Настройка TabView

Этот XAML задает свойство CanTearOutTabs для true и настраивает обработчики событий вырезания вкладки.

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

Создание и отслеживание нового окна

Для разрыховки вкладок требуется создать в приложении новые окна и управлять ими.

Совет

Приложение коллекции WinUI включает класс WindowHelper, упрощающий управление окнами в приложении. Его можно скопировать из GitHub в репозитории коллекции WinUI: WindowHelper.cs. Мы рекомендуем использовать этот вспомогательный класс для реализации отсоединения вкладок. Ознакомьтесь с TabViewWindowingSamplePage на сайте GitHub, чтобы узнать, как его использовать.

В этой статье вспомогательные методы копируются из WindowHelper.cs, но изменяются и отображаются встроенно, для удобства чтения.

Создается список для отслеживания всех активных окон здесь, в App.xaml.cs. Метод OnLaunched обновляется для отслеживания окна после его создания. (Это не требуется, если используется класс 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();
}

Когда начинается разрыв вкладки, запрашивается новое окно. Здесь переменная tabTearOutWindow предоставляет доступ к новому окну после его создания. Вспомогательные методы CreateWindow и TrackWindow создают новое окно и добавляют его в список активного отслеживания окон.

После создания нового окна необходимо создать новую страницу и задать ее в качестве содержимого окна. Новый элемент Page должен содержать элемент управления TabView, в который вы переместите отсоединенную вкладку в обработчике событий TabTearOutRequested.

Совет

В этом примере мы создадим новый класс MainPage, так как он содержит только пустой tabView (вкладки не добавляются непосредственно в XAML). Если MainPage включает другие элементы пользовательского интерфейса, которые не должны отображаться в отдельном окне, вы можете создать отдельную страницу, содержащую только необходимые элементы (включая по крайней мере TabView), и создать экземпляр этой страницы.

Наконец, назначьте AppWindow.Id нового окна свойству args.NewWindowId. Это будет использоваться в свойстве TabViewTabTearOutRequestedEventArgs.NewWindowId, чтобы получить доступ к окну из этого обработчика событий.

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

Закрытие окна при закрытии последней вкладки

Как упоминалось ранее, может потребоваться закрыть окно при закрытии последней вкладки в 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)
    {
        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;
}

Перемещение вкладки в новое окно

После предоставления нового окна необходимо удалить перетянутую вкладку из sender TabView и добавить ее в TabView в новом окне. В этом примере вспомогательный метод public AddTabToTabs позволяет получить доступ к TabView в новом экземпляре MainPage из исходного экземпляра страницы, чтобы добавить в него вырванную вкладку.

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

Перетащите вырванную вкладку на другой Tab View

Когда вкладка была вырвана и помещена в новое окно, как показано на предыдущих шагах, может произойти одно из двух действий:

  • Пользователь может удалить вкладку и остаться в новом окне. Процесс демонтажа заканчивается здесь, и никаких событий больше не возникает.
  • Пользователь может продолжать перетаскивать вырванную вкладку обратно на существующий элемент управления TabView. В этом случае процесс продолжается, и создаются несколько дополнительных событий, чтобы удалить вкладку из исходного TabView и вставить внешнюю вкладку в существующий TabView.

Когда вкладка перетаскивается над существующим компонентом TabView, инициируется событие ExternalTornOutTabsDropping. В обработчике событий можно определить, разрешена ли вставка вкладки в этот tabView. В большинстве случаев необходимо задать для свойства allowDrop args.значение только для true. Однако если перед настройкой этого свойства необходимо выполнить какие-либо проверки, это можно сделать здесь. Если установить для AllowDrop значение false, действие перетаскивания вкладки продолжится, и событие ExternalTornOutTabsDropped не будет вызвано.

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

Если в обработчике события ExternalTornOutTabsDropping устанавливается AllowDrop на true, то событие ExternalTornOutTabsDropped немедленно вызывается.

Примечание.

Dropped в имени события напрямую не соответствует идее действия перетаскивания в API перетаскивания. Здесь пользователю не нужно отпускать вкладку, чтобы выполнить действие удаления. Событие возникает, пока вкладка хранится над полосой вкладок, и код выполняется для удаления вкладки в TabView.

Обработчик событий ExternalTornOutTabsDropped следует тому же шаблону, что и событие TabTearOutRequested, но инвертировано; Необходимо удалить вкладку из исходного TabView и вставить ее в sender TabView.

sender TabView — это элемент управления, в который вставляется вкладка, поэтому мы используем вспомогательный метод GetParentTabView для поиска исходной вкладки. Он начинается с вырванного tabViewItem и использует VisualTreeHelper для перехода по визуальному дереву и поиску элемента TabView, к которому принадлежит элемент. После обнаружения TabView элемент TabViewItem удаляется из коллекции TabItems и вставляется в коллекцию TabItems TabView sender TabView по индексу, указанному 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;
}

Совет

Если вы используете набор средств сообщества Windows, можно воспользоваться вспомогательным методом FindAscendant в DependencyObjectExtensions, а не GetParentTabView.

Отображение вкладок TabView в строке заголовка окна

Вместо того, чтобы вкладки занимали собственную строку под строкой заголовка окна, можно объединить их в одну и ту же область. Это позволит сэкономить пространство по вертикали для содержимого и придать приложению современный вид.

Так как пользователь может перетаскивать окно по его заголовку, чтобы изменить положение окна, важно, чтобы строка заголовка не была полностью заполнена вкладками. Таким образом, при отображении вкладок в строке заголовка необходимо указать часть строки заголовка, зарезервированную в качестве перетаскиваемой области. Если не указать область, которую можно перетаскивать, вся верхняя панель будет перетаскиваться, что помешает вкладкам получать входные события. Если ваш TabView будет отображаться в строке заголовка окна, всегда следует включить TabStripFooter в TabView и пометить его как перетаскиваемую область.

Дополнительные сведения см. в статье Настройка заголовка окна.

вкладки в строке заголовка

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

Примечание.

Как получить ссылку на окно (currentWindow) может отличаться в зависимости от того, как вы отслеживаете окна в приложении. Дополнительные сведения см. в разделе Закрытие окна при закрытии последней вкладки и создание и отслеживание нового окна в этой статье.

Руководство по клавиатуре для разработчиков

Совет

Дополнительные сведения о встроенной поддержке клавиатуры см. раздел Навигация с помощью клавиатуры ранее в этой статье.

Некоторые приложения могут потребовать более расширенного управления с клавиатуры. Рассмотрите возможность реализации следующих сочетаний клавиш, если они подходят для вашего приложения.

Предупреждение

Если вы добавляете TabView в существующее приложение, возможно, вы уже создали сочетания клавиш, которые соответствуют рекомендуемым сочетаниям клавиш TabView. В этом случае необходимо решить, следует ли использовать существующие сочетания клавиш или предложить пользователю интуитивно понятный интерфейс для работы с вкладками.

  • CTRL+T должен открыть новую вкладку. Обычно эта вкладка заполняется предопределенным документом или создается пустой с простым способом выбора его содержимого. Если пользователь должен выбрать содержимое для новой вкладки, рассмотрите возможность переноса фокуса ввода в элемент управления выбором содержимого.
  • CTRL+ W должен закрыть выбранную вкладку. Помните, что TabView автоматически выберет следующую вкладку.
  • CTRL+ SHIFT+ T должны открывать недавно закрытые вкладки (или более точно открывать новые вкладки с тем же содержимым, что и недавно закрытые вкладки). Начните с последней закрытой вкладки и возвращайтесь назад по времени при каждом следующем нажатии этого сочетания клавиш. Обратите внимание на то, что для этого потребуется хранение списка недавно закрытых вкладок.
  • CTRL+ 1 должен выбрать первую вкладку в списке вкладок. Аналогичным образом, нажатие клавиш CTRL+2 должно выбирать вторую вкладку, CTRL+3 — третью, и так далее до CTRL+8.
  • CTRL+ 9 должен выбрать последнюю вкладку в списке вкладок независимо от количества вкладок в списке.
  • Если вкладки поддерживают не только команду закрытия (а, например, дублирование или закрепление вкладки), используйте контекстное меню для отображения всех доступных действий, которые можно выполнить с вкладкой.

Реализация поведения клавиатуры, аналогичного браузеру

В этом примере реализуется ряд описанных выше рекомендаций для TabView. В частности, в этом примере реализованы CTRL+T, CTRL+W, CTRL+1-8и 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 и WinUI 2

Важный

Сведения и примеры, описанные в этой статье, оптимизированы для приложений, использующих пакет SDK для приложений Для Windows и WinUI 3, но обычно применимы к приложениям UWP, использующим WinUI 2. См. справочник по API UWP для конкретных сведений и примеров платформы.

В этом разделе содержатся сведения, необходимые для использования элемента управления в приложении UWP или WinUI 2.

Элемент управления TabView для приложений UWP включен в состав WinUI 2. Для получения дополнительной информации, включая инструкции по установке, см. WinUI 2. API для этого элемента управления существуют в пространстве имен Microsoft.UI.Xaml.Controls.

API-интерфейсы для отсоединения вкладок не включены в WinUI 2 для TabView.

Мы рекомендуем использовать последнюю версию WinUI 2, чтобы получить самые актуальные стили, шаблоны и функции для всех элементов управления. WinUI 2.2 или более поздней версии содержит новый шаблон для этого элемента управления, использующего округленные углы. Дополнительную информацию см. в разделе Радиус угла.

Чтобы использовать код в этой статье с WinUI 2, используйте псевдоним в XAML (мы используем muxc) для представления API библиотеки пользовательского интерфейса Windows, включенных в проект. Дополнительные сведения см. в статье Начало работы с WinUI 2.

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

<muxc:TabView />