痕迹栏
BreadcrumbBar 提供页面或文件夹当前位置的直接路径。 该控件通常用于这样的情况:用户的导航轨迹(在文件系统或菜单系统中)需要持续可见,并且用户可能需要返回到前一位置。
这是正确的控件吗?
痕迹导航栏让用户可以在浏览应用或文件夹时跟踪他们的位置,并可快速跳回到路径中的前一位置。
如果用于跳转到当前位置的路径是相关的,请使用 BreadcrumbBar。 在文件夹管理器中,以及在用户可以在应用中深入导航多个级别时,经常使用此 UI。
痕迹导航栏 UI
痕迹导航栏在水平行中显示每个节点,各个节点用“>”符号分隔。
如果调整应用大小后没有足够的空间可用于显示所有节点,则痕迹导航将会折叠并用省略号来代替最左侧的节点。 单击省略号会打开一个浮出窗口以显示折叠的节点。
结构
下图显示了 BreadcrumbBar
控件的各个部件。 可以使用轻型样式设置修改某些部件的外观。
建议
- 如果你有多个导航级别并希望用户能够返回到任何前一级别,请使用痕迹导航栏。
- 如果你只有 2 个可能的导航级别,请不要使用痕迹导航栏。 使用简单的后退导航便已足够。
- 将当前位置显示为痕迹导航栏中的最后一个项。 但是,如果用户单击当前项,你通常不希望执行任何导航。 (要让用户重新加载当前页面或数据,请考虑提供专用的“重新加载”选项。)
UWP 和 WinUI 2
重要
本文中的信息和示例是针对使用 Windows App SDK 和 WinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请查看 UWP API 参考。
本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。
UWP 应用的痕迹导航栏需要 WinUI 2。 有关详细信息(包括安装说明),请参阅 WinUI 2。 此控件的 API 存在于 Microsoft.UI.Xaml.Controls 命名空间中。
- WinUI 2 Apis:BreadcrumbBar 类
- 打开 WinUI 2 库应用,了解 BreadcrumbBar 的实际应用。 WinUI 2 库应用包括大多数 WinUI 2 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码。
要将本文中的代码与 WinUI 2 配合使用,请使用 XAML 中的别名(我们使用 muxc
)来表示项目中包含的 Windows UI 库 API。 有关详细信息,请参阅 WinUI 2 入门。
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
<muxc:BreadcrumbBar />
创建痕迹导航栏
- 重要 API:BreadcrumbBar 类
WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码
此示例演示如何使用默认样式创建痕迹导航栏。 可将痕迹导航栏放置在应用 UI 中的任何位置。 通过设置 ItemsSource 属性来填充痕迹导航。 在此处,该属性设置为痕迹导航栏中显示的字符串数组。
<BreadcrumbBar x:Name="BreadcrumbBar1"/>
BreadcrumbBar1.ItemsSource =
new string[] { "Home", "Documents", "Design", "Northwind", "Images", "Folder1", "Folder2", "Folder3" };
ItemsSource
痕迹导航栏没有 Items
属性,而只有 ItemsSource 属性。 这意味着,无法在 XAML 中填充痕迹导航,也无法通过在代码中将痕迹导航直接添加到 Items
集合来填充痕迹导航。 为此,应该创建一个集合,并在代码中或使用数据绑定将 ItemsSource
属性连接到该集合。
可将 ItemsSource 设置为任何数据类型的集合,以满足应用的需求。 集合中的数据项既用于在栏中显示痕迹导航,也用于在单击痕迹导航栏中的项时进行导航。 在本页面上的示例中,我们将创建一个简单的 struct
(名为 Crumb
),其中包含一个显示在痕迹导航栏中的标签,以及一个数据对象,该对象保存了用于导航的信息。
public readonly struct Crumb
{
public Crumb(String label, object data)
{
Label = label;
Data = data;
}
public string Label { get; }
public object Data { get; }
public override string ToString() => Label;
}
ItemTemplate
默认情况下,痕迹导航栏显示集合中每个项的字符串表示形式。 如果集合中的数据项没有相应的 ToString
重写,你可以使用 ItemTemplate 属性指定一个数据模板,用于定义这些项在痕迹导航栏中的显示方式。
例如,如果痕迹导航集合是 StorageFolder 对象的列表,则你可以提供一个数据模板并如下所示将其绑定到 DisplayName 属性。
ObservableCollection<StorageFolder> Breadcrumbs =
new ObservableCollection<StorageFolder>();
<BreadcrumbBar x:Name="FolderBreadcrumbBar"
ItemsSource="{x:Bind Breadcrumbs}">
<BreadcrumbBar.ItemTemplate>
<DataTemplate x:DataType="StorageFolder">
<TextBlock Text="{x:Bind DisplayName}"/>
</DataTemplate>
</BreadcrumbBar.ItemTemplate>
</BreadcrumbBar>
ItemClicked
处理 ItemClicked 事件,以导航到用户在痕迹导航栏中单击的项。 当前位置通常显示为痕迹导航栏中的最后一个项,因此,如果你不想要重新加载当前位置,应在事件处理程序中包含一项检查。
此示例检查 Index,以确定单击的 Item 是否是集合中的最后一个项,即当前位置。 如果是,则不发生导航。
// Breadcrumbs is set as BreadcrumbBar1.ItemsSource.
List<Crumb> Breadcrumbs = new List<Crumb>();
...
private void BreadcrumbBar1_ItemClicked(muxc.BreadcrumbBar sender, muxc.BreadcrumbBarItemClickedEventArgs args)
{
if (args.Index < Breadcrumbs.Count - 1)
{
var crumb = (Crumb)args.Item;
Frame.Navigate((Type)crumb.Data);
}
}
轻型样式
可以修改默认 Style 和 ControlTemplate 以使控件具有唯一的外观。 请参阅 BreadcrumbBar API 文档的“控件样式和模板”部分,以查看可用主题资源的列表。 有关详细信息,请参阅设置控件样式一文中的轻量级样式设置部分。
代码示例
此示例演示如何在简单的文件资源管理器方案中使用痕迹导航栏。 列表视图显示所选图片或音乐库的内容,并让用户深入到子文件夹。 痕迹导航栏放置在列表视图的标题中,显示当前文件夹的路径。
<Grid>
<ListView x:Name="FolderListView" Margin="24,0"
IsItemClickEnabled="True"
ItemClick="FolderListView_ItemClick">
<ListView.Header>
<BreadcrumbBar x:Name="FolderBreadcrumbBar"
ItemsSource="{x:Bind Breadcrumbs}"
ItemClicked="FolderBreadcrumbBar_ItemClicked">
</BreadcrumbBar>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
public sealed partial class MainPage : Page
{
List<IStorageItem> Items;
ObservableCollection<object> Breadcrumbs =
new ObservableCollection<object>();
public MainPage()
{
this.InitializeComponent();
InitializeView();
}
private void InitializeView()
{
// Start with Pictures and Music libraries.
Items = new List<IStorageItem>();
Items.Add(KnownFolders.PicturesLibrary);
Items.Add(KnownFolders.MusicLibrary);
FolderListView.ItemsSource = Items;
Breadcrumbs.Clear();
Breadcrumbs.Add(new Crumb("Home", null));
}
private async void FolderBreadcrumbBar_ItemClicked(muxc.BreadcrumbBar sender, muxc.BreadcrumbBarItemClickedEventArgs args)
{
// Don't process last index (current location)
if (args.Index < Breadcrumbs.Count - 1)
{
// Home is special case.
if (args.Index == 0)
{
InitializeView();
}
// Go back to the clicked item.
else
{
var crumb = (Crumb)args.Item;
await GetFolderItems((StorageFolder)crumb.Data);
// Remove breadcrumbs at the end until
// you get to the one that was clicked.
while (Breadcrumbs.Count > args.Index + 1)
{
Breadcrumbs.RemoveAt(Breadcrumbs.Count - 1);
}
}
}
}
private async void FolderListView_ItemClick(object sender, ItemClickEventArgs e)
{
// Ignore if a file is clicked.
// If a folder is clicked, drill down into it.
if (e.ClickedItem is StorageFolder)
{
StorageFolder folder = e.ClickedItem as StorageFolder;
await GetFolderItems(folder);
Breadcrumbs.Add(new Crumb(folder.DisplayName, folder));
}
}
private async Task GetFolderItems(StorageFolder folder)
{
IReadOnlyList<IStorageItem> itemsList = await folder.GetItemsAsync();
FolderListView.ItemsSource = itemsList;
}
}
public readonly struct Crumb
{
public Crumb(String label, object data)
{
Label = label;
Data = data;
}
public string Label { get; }
public object Data { get; }
public override string ToString() => Label;
}