选项卡视图
可以通过 TabView 控件显示一组选项卡及其相应的内容。 TabView 控件可用于显示内容的多个页面(或文档),同时允许用户重新排列、关闭或打开新选项卡。
这是正确的控件吗?
通常,选项卡式 UI 采用两种不同的样式之一,这些样式在函数和外观上有所不同:
- 静态选项卡 是通常在设置窗口中找到的选项卡类型。 它们包含一定数目的页面,这些页面的顺序固定且通常包含预定义的内容。
- 文档选项卡是在浏览器(例如 Microsoft Edge)中发现的选项卡类型。 用户可以创建、删除和重新排列选项卡;在窗口之间移动选项卡;更改选项卡的内容。
默认情况下,TabView 配置为提供文档选项卡。 我们建议使用 TabView,当用户能够:
- 动态打开、关闭或重新排列选项卡。
- 直接在选项卡中打开文档或网页。
- 在窗口之间拖放选项卡。
TabView API 允许为静态选项卡配置控件。 但是,若要遵循 Windows 设计指南,如果有多个静态导航项,请考虑使用 NavigationView 控件。
结构
选项卡式 UI 是使用 TabView 控件和一个或多个 TabViewItem 控件创建的。 TabView 承载 TabViewItem 的实例,它表示单个选项卡及其内容。
TabView 部件
此图显示了 TabView 控件的各个部分。 制表条 具有页眉和页脚,但与文档不同,制表条的页眉和页脚分别位于条带的最左侧和最右侧。
TabViewItem 部件
此图显示了 TabViewItem 控件的各个部分。 虽然内容显示在 TabView 控件内,但内容实际上是 TabViewItem 的一部分。
建议
选项卡选择
大多数用户只需使用 Web 浏览器即可获得文档选项卡的使用体验。 他们在你的应用中使用文档选项卡时,会根据自己的体验预期你的选项卡的具体行为。
不管用户以何种方式与一组文档选项卡交互,始终应有一个活动选项卡。如果用户关闭所选选项卡或将所选选项卡移到另一窗口中,则另一选项卡应成为活动选项卡。为此,TabView 会尝试自动选择下一选项卡。如果你觉得应用应该允许 TabView 的选项卡处于未选中状态,则应让 TabView 的内容区域直接显示为空白。
键盘导航
默认情况下,TabView 支持许多常见的键盘导航方案。 此部分介绍内置功能,并提供可能对某些应用有用的其他功能的建议。
Tab 键和光标键的行为
当焦点移到 TabStrip 区域时,所选 TabViewItem 获得焦点。 然后,用户可以使用左箭头键和右箭头键将焦点(而非选择)移动到选项卡带中的其他选项卡。 箭头焦点限制在选项卡条和“添加选项卡(+)”按钮(如果存在)中。 若要将焦点移出制表区区域,用户可以按 Tab 键,这将将焦点移动到下一个可聚焦元素。
通过 Tab 移动焦点
移动焦点
箭头键不循环焦点
选择选项卡
当某个 TabViewItem 获得焦点以后,按空格键或Enter 键即可选择该 TabViewItem。
使用箭头键移动焦点,然后按 空格 选择选项卡。
选择相邻选项卡的快捷方式
按 Ctrl 键 + Tab 键以选择下一个 TabViewItem。 按 Ctrl+Shift+Tab 选择上一个 TabViewItem。 出于这些目的,选项卡列表是“循环的”,因此选择下一个选项卡时选择最后一个选项卡将导致第一个选项卡被选中。
关闭选项卡
按 Ctrl + F4 触发 TabCloseRequested 事件。 请根据需要处理该事件并关闭选项卡。
提示
有关详细信息,请参阅本文后面的 面向开发人员的键盘指南。
创建选项卡视图
- 重要 API:TabView 类、TabViewItem 类
WinUI 3 画廊 应用程序包括大多数 WinUI 3 控件、特性和功能的交互式示例。 从 Microsoft Store 获取应用,或在 GitHub 上获取源代码。
本节中的示例演示了配置 TabView 控件的各种方法。
选项卡视图项
TabView 中的每个选项卡都由 TabViewItem 控件表示,该控件包括选项卡条带中显示的选项卡以及选项卡条带下方显示的内容。
配置选项卡
对于每个 TabViewItem,可以设置标题和图标,并指定用户是否可以关闭选项卡。
- Header 属性通常设置为提供选项卡的描述性标签的字符串值。但是,
Header
属性可以是任何对象。 还可以使用 HeaderTemplate 属性来指定 DataTemplate,定义如何显示绑定的标头数据。 - 设置 IconSource 属性以指定选项卡的图标。
- 默认情况下,选项卡显示关闭按钮。 可以将 IsClosable 属性设置为
false
,以确保用户无法关闭选项卡。
对于 TabView,可以配置应用于所有选项卡的多个选项。
- 默认情况下,可关闭选项卡始终显示关闭按钮 (X)。 可以将 CloseButtonOverlayMode 属性设置为
OnPointerOver
以更改此行为。 在这种情况下,若选项卡可以关闭,则所选选项卡始终显示关闭按钮;而未选中的选项卡只有在可以关闭且用户的指针悬停在上面时才显示关闭按钮。 - 可以设置 TabWidthMode 属性,以更改选项卡的大小。 (
TabViewItem
上忽略Width
属性。)以下是 TabViewWidthMode 枚举中的选项:Equal
- 每个选项卡的宽度相同。 这是默认值。SizeToContent
- 每个选项卡都会根据其内的内容调整宽度。Compact
- 未选择的选项卡折叠,仅显示其图标。 所选选项卡会进行调整以显示其内容。
内容
所选选项卡中显示的元素将添加到 TabViewItem的 Content 属性中。 TabViewItem 是 ContentControl,因此你可以添加任何类型的对象作为内容。 还可以将 DataTemplate 应用于 ContentTemplate 属性。 有关详细信息,请参阅 ContentControl 类。
本文中的示例演示了将文本直接添加到 XAML 中 Content
元素的简单案例。 但是,实际 UI 通常更为复杂。 添加复杂 UI 作为选项卡内容的一种常见方法是将其封装在 UserControl 或 Page中,并将其添加为 TabViewItem 的内容。 此示例假定你的应用具有一个名为 PictureSettingsControl
的 XAML UserControl。
<TabViewItem>
<TabViewItem.Content>
<local:PictureSettingsControl/>
</TabViewItem.Content>
</TabViewItem>
静态选项卡
此示例显示了一个简单的 TabView,其中包含两个 静态选项卡。 在 XAML 中,这两个选项卡作为 TabView 的内容被添加。
若要使 TabView 静态,请使用以下设置:
- 将 IsAddTabButtonVisible 属性设置为
false
以隐藏 添加选项卡 按钮,并阻止引发 AddTabButtonClick 事件。 - 将 CanReorderTabs 属性设置为
false
,以防止用户将选项卡拖入不同的顺序。 - 在每个 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
文件中,添加一个公共属性,该属性允许你从承载 TabView 的 Page
访问 Window
实例。
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 控件(通常是在新窗口中)时会发生的情况。
从 Windows 应用 SDK 1.6 开始,TabView 具有 CanTearOutTabs 属性,你可以将其设置为提供增强的体验,用于将选项卡拖出到新窗口。 当用户将选项卡拖出启用了此选项的制表条时,将在拖动过程中立即创建一个新窗口,允许用户将其拖动到屏幕边缘,以最大化窗口或将窗口贴靠在一个平滑动作中。 此实现也不使用拖放 API,因此不受这些 API 中的任何限制的影响。
将 CanTearOutTabs 属性设置为 true
时,会触发选项卡分离事件,而非拖放事件。 若要实现选项卡分离,必须处理以下事件:
-
当选项卡首次从标签栏中拖出时,会发生此事件。 处理它以创建一个新的窗口和 TabView,选项卡将移动到那里。
-
提供新窗口后,将发生此事件。 处理它,将已分离的选项卡从原始 TabView 移动到新窗口中的 TabView。
-
当在现有 TabView 上拖动已撕裂的选项卡时,会发生此事件。 在正在接收拖动选项卡的 TabView 中处理,以指明是否应接受该选项卡。
-
当在现有 TabView 上拖动已分离的选项卡并且
ExternalTornOutTabsDropping
事件指示允许放置时,会发生此事件。 在接收分离选项卡的 TabView 中进行处理,将选项卡从原始 TabView 中移除,并将其插入到接收 TabView 的指定索引处。
启用 Tab 分离时,不会引发这些事件:TabDragStarting、TabStripDragOver、TabStripDrop、TabDragCompleted、TabDroppedOutside。
谨慎
在以管理员身份提升的进程中,支持 Tab 拆解。
以下示例展示了如何实现事件处理程序来支持选项卡分离。
设置 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 Gallery 应用包括一个 WindowHelper
类,使管理应用中的窗口更加简单。 可以从 GitHub 的 WinUI Gallery 仓库中复制它:WindowHelper.cs。 建议使用此帮助程序类来实现选项卡拆解。请参阅 GitHub 上的 TabViewWindowingSamplePage,了解其用法。
在本文中,帮助程序方法从 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
帮助程序方法会创建新窗口并将其添加到活动窗口跟踪列表中。
创建新窗口后,需要创建新的页面并将其设置为窗口的内容。 新页面必须包含一个 TabView 控件,你将在 TabTearOutRequested
事件处理程序中将已分离选项卡移动到该选项卡。
提示
在此示例中,我们创建了一个新的 MainPage
类,因为它仅包含空的 TabView(XAML 中没有直接添加选项卡)。 如果 MainPage
包含其他不应显示在分离窗口中的 UI 元素,那么您可以创建一个单独的页面,其中仅包含您所需的元素(至少需要包含一个 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
帮助程序方法使你能够从原始页面实例访问新 MainPage
实例中的 TabView,以便向其添加已分离选项卡。
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);
}
将已分离选项卡拖到另一个 TabView
当选项卡被撕裂并放入新窗口中时,如前面的步骤所示,可能会出现以下两种情况之一:
- 用户可以拖放该选项卡,并使其留在新窗口中。 分离过程到此结束,不会引发更多事件。
- 用户可以继续将已撕裂的选项卡拖回到现有的 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 集合中删除,并插入到 sender
TabView 的 TabItems
集合中由 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 社区工具包,则可以在工具包的 DependencyObjectExtensions 中使用 FindAscendant
辅助方法,而不是 GetParentTabView
。
在窗口标题栏中显示 TabView 选项卡
可以将标签页和窗口标题栏合并到同一区域,而不是让标签页在窗口标题栏下方单独占据一行。 这样可以节省内容的垂直空间,为应用带来现代的观感。
因为用户可以通过拖动标题栏来重新定位窗口,因此很重要的是,标题栏不应该被选项卡完全填满。 因此,在标题栏中显示选项卡时,必须指定要保留为可拖动区域的标题栏的一部分。 如果未指定可拖动区域,则整个标题栏将可拖动,从而阻止选项卡接收输入事件。 如果 TabView 将显示在窗口的标题栏中,则应始终在 TabView 中包括一个 TabStripFooter 并将其标记为可拖动区域。
有关详细信息,请参阅标题栏自定义
标题栏中的
<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
重要
本文中的信息和示例针对使用 Windows 应用 SDK 和 WinUI 3的应用进行优化,但通常适用于使用 WinUI 2的 UWP 应用。 有关特定于平台的信息和示例,请参阅 UWP API 参考。
本部分包含需要在 UWP 或 WinUI 2 应用中使用该控件的信息。
UWP 应用的 TabView 控件包含在 WinUI 2 中。 有关详细信息(包括安装说明),请参阅 WinUI 2。 此控件的 API 存在于 Microsoft.UI.Xaml.Controls 命名空间中。
Tab 分离 API 不包括在 WinUI 2 版本的 TabView 中。
- WinUI 2 API:TabView 类、TabViewItem 类
- 打开 WinUI 2 演示应用并来体验 TabView 的实际效果。 WinUI 2 库应用包括大多数 WinUI 2 控件、特性和功能的交互式示例。 从 Microsoft Store 获取应用,或在 GitHub上获取源代码。
建议使用最新的 WinUI 2 来获取所有控件的最新样式、模板和功能。 WinUI 2.2 或更高版本包含此控件的新模板,该模板使用圆角。 有关详细信息,请参阅圆角半径。
若要将本文中的代码与 WinUI 2 配合使用,请使用 XAML 中的别名(我们使用 muxc
)来表示项目中包括的 Windows UI 库 API。 有关详细信息,请参阅 WinUI 2 入门。
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
<muxc:TabView />