WPF 面包屑导航栏






4.93/5 (46投票s)
WPF 面包屑导航栏实现。
引言
这是一个类似 Vista 的 WPF 面包屑导航栏,支持 HierarchicalTemplates
、按需加载、动态路径转换等等。
背景
BreadcrumbBar
是我正在开发的名为 Odyssey 的免费 WPF 控件库的一部分,纯粹是为了好玩。它类似于 Vista 的面包屑导航栏,实际上是一个多控件栏,包括面包屑部分、一个可编辑的 ComboBox
、一个进度条和一个按钮区域。
BreadcrumbBar
是一个用于显示分层数据源的控件。分层结构通过 HierarchicalDataTemplate
来描述,这与 TreeView
控件的方式相同。BreadcrumbBar
只包含一个 BreadcrumbItem
,即 Root
属性。Root
可以通过 XAML 或代码直接分配给 BreadcrumbItem
,或者分配给一个分层数据源。在后一种情况下,会自动构建虚拟的 BreadcrumbItem
,并且可以通过 RootItem
属性访问根 BreadcrumbItem
。与 TreeView
不同,BreadcrumbBar
只能有一个根项。
BreadcrumbItem
一个 HeaderedItemsControl
,其中包含一个项目集合,这些项目代表数据源的下一级分层结构。TreeViewItem
和 BreadcrumbItem
之间的区别在于,BreadcrumbItem
只显示选定的项,而 TreeViewItem
显示所有项。
由于标题是一个视觉元素,不一定能转换为字符串,因此 Trace
属性用于从所有选定的 BreadcrumbItem
构建 BreadcrumbBar
的 Path
,反之亦然。Trace
的类型是 object
;因此,可以分配字符串,也可以分配 XmlNode
。如果你想将值检索为字符串,可以使用 TrailValue
属性。
Image
属性指定了将在 BreadcrumbBar
中为选定项显示的图像 ImageSource
,以及在 BreadcrumbItem
的下拉菜单上显示的图像。
注意:由于图像可以在 BreadcrumbBar
和下拉菜单上显示,所以它不能是一个 Image
控件,因为一个控件只能有一个父级。
BreadcrumbButton
一个 HeaderedItemsControl
,它打开一个下拉菜单以选择下一个面包屑项。
注意:BreadcrumbButton
是 BreadcrumbItem
的一部分的辅助控件,不应直接使用。
重要的依赖属性
BreadcrumbBar.Root
指定第一个面包屑项。这可以是一个BreadcrumbItem
,也可以是一个分层数据源。BreadcrumbBar.Path
获取或设置BreadcrumbBar
的路径。BreadcrumbBar.SelectedItem
获取选定的数据项或BreadcrumbItem
。BreadcrumbBar.SelectedBreadcrumb
获取选定的(虚拟)BreadcrumbItem
。BreadcrumbBar.TraceBinding
获取或设置BreadcrumbBar
的Path
,该路径由每个选定的项表示,从根项开始。BreadcrumbBar.ImageBinding
指定一个绑定到项的绑定,该项在与数据源结合使用时,为BreadcrumbItem
提供Image
属性。BreadcrumbItem.Trace
获取或设置构建路径所需的Trace
属性。BreadcrumbItem.Image
获取或设置Image
属性,该属性用于获取BreadcrumbBar
和下拉菜单中每个项的图像。
使用代码
这是一个在 XAML 中描述 BreadcrumbBar
并将嵌套的 BreadcrumbItem
分配给 Root
属性的示例。
<odc:BreadcrumbBar x:Name="bar"
Path="Computer\C:\"br> PopulateItems="BreadcrumbBar_PopulateItems"
TraceBinding="{Binding Folder}"
ImageBinding="{Binding Image}"
PathConversion="BreadcrumbBar_PathConversion">
以下示例展示了如何使用数据源来获取面包屑项,以及如何使用 TraceBinding
属性为每个虚拟 BreadcrumbItem
绑定 Trace
属性。
<Window x:Class="BreadcrumbWithDataSourceExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:odc="clr-namespace:Odyssey.Controls;assembly=Odyssey"
Background="LightSteelBlue"
Title="BeadcrumbBar Demo: Using XmlDataProvider as Root Property"
Height="300" Width="700">
<Window.Resources>
<XmlDataProvider x:Key="dataProvider" XPath="bc">
<x:XData>
<bc xmlns="" title="Desktop">
<bc title="Computer">
<bc title="C:" >
<bc title="Windows" >
<bc title="System32"/>
<bc title="ie7"/>
<bc title="Microsoft.NET"/>
<bc title="Fonts"/>
<bc title="Driver Cache"/>
<bc title="inf"/>
</bc>
<bc title="Program Files">
<bc title="Visual Studio"/>
<bc title="Office"/>
</bc>
<bc title="Users">
<bc title="Administrator"/>
<bc title="Guest"/>
</bc>
</bc>
<bc title="D:"/>
</bc>
<bc title="Network">
<bc title="odyssey">
<bc title="public"/>
<bc title="private"/>
</bc>
<bc title="daedalus">
<bc title="system"/>
<bc title="confidential"/>
</bc>
</bc>
</bc>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate DataType="bc"
ItemsSource="{Binding XPath=*}">
<TextBlock Text="{Binding XPath=@title}"
Foreground="Red"/>
</HierarchicalDataTemplate>
</Window.Resources>
<DockPanel Margin="5">
<odc:BreadcrumbBar x:Name="bar" DockPanel.Dock="Top"
TraceBinding="{Binding XPath=@title}"
Root="{StaticResource dataProvider}"/>
<Grid></Grid>
</DockPanel>
</Window>
也可以不使用 TraceBinding
和 ImageBinding
来绑定 Trace
和 Image
属性,如下例所示,但使用 TraceBinding
和 ImageBinding
可以使 XAML 代码更简洁。
<odc:BreadcrumbBar>
<odc:BreadcrumbBar.Style>
<Style TargetType="{x:Type odc:BreadcrumbItem}">
<Setter Property="Trace" Value="{Binding XPath=@title}"/>
</Style>
</odc:BreadcrumbBar.Style>
</odc:BreacrumbBar>
按需填充面包屑项
以下代码段演示了如何使用 BreadcrumbBar
的 PopulateItems
事件按需填充面包屑项。如果您无法或不想在数据源中指定所有可能的层级结构,例如,当您想使用面包屑导航栏来选择文件路径时,这很有用。因此,BreadcrumbBar
有一个名为 PopulateItems
的 RoutedEvent
,当 BreadcrumbItem
需要访问其项时就会触发。
private void BreadcrumbBar_PopulateItems(object sender,
Odyssey.Controls.PopulateItemsEventArgs e)
{
if (e.Item.Items.Count == 0)
{
BreadcrumbBar bar = sender as BreadcrumbBar;
string path = bar.PathFromBreadcrumbItem(e.Item);
string trace = e.Item.TraceValue;
if (trace.Equals("Computer"))
{
string[] dirs = System.IO.Directory.GetLogicalDrives();
foreach (string s in dirs)
{
string dir = s;
if (s.EndsWith(bar.SeparatorString))
dir = s.Remove(s.Length - bar.SeparatorString.Length,
bar.SeparatorString.Length);
FolderItem fi = new FolderItem();
fi.Folder = dir;
e.Item.Items.Add(fi);
}
e.Handled = true;
}
else
{
try
{
string[] paths = System.IO.Directory.GetDirectories(path + "\\");
foreach (string s in paths)
{
string file = System.IO.Path.GetFileName(s);
FolderItem fi = new FolderItem();
fi.Folder = file;
e.Item.Items.Add(fi);
}
}
catch { }
e.Handled = true;
}
}
}
路径转换
路径转换用于解析编辑框中文本的层级结构,反之亦然。例如,数据源具有以下结构
- 桌面
- 电脑
- C
- Windows
- 程序文件
- D
- 网络
- 计算机 A
- 计算机 B
- 网络
- C
- 电脑
但是,比起显示为 Desktop/Network/Computer A,更希望显示为 \\Computer A。
为此,有一个名为 PathConversion
的 RoutedEvent
,它允许您使用代码在数据结构和路径之间进行转换。以下代码段显示了 FileBrowserDemo 中的一个片段(我必须承认,这段代码不是很优雅,但它展示了如何使用它)。
private void BreadcrumbBar_PathConversion(object sender, PathConversionEventArgs e)
{
if (e.Mode == PathConversionEventArgs.ConversionMode.DisplayToEdit)
{
if (e.DisplayPath.StartsWith(@"Computer\",
StringComparison.OrdinalIgnoreCase))
{
e.EditPath = e.DisplayPath.Remove(0, 9);
}
else if (e.DisplayPath.StartsWith(@"Network\",
StringComparison.OrdinalIgnoreCase))
{
string editPath = e.DisplayPath.Remove(0, 8);
editPath = @"\\" + editPath;
e.EditPath = editPath;
}
}
else
{
if (e.EditPath.StartsWith("c:", StringComparison.OrdinalIgnoreCase))
{
e.DisplayPath = @"Desktop\Computer\" + e.EditPath;
}
else if (e.EditPath.StartsWith(@"\\"))
{
e.DisplayPath = @"Desktop\Network\" + e.EditPath.Remove(0, 2);
}
}
}
关注点
有关更多信息和更新,请访问 我的网站。
历史
- 2008-09-15 - 发布初始版本。