65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 面包屑导航栏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (46投票s)

2008 年 9 月 15 日

CPOL

4分钟阅读

viewsIcon

176310

downloadIcon

4641

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,其中包含一个项目集合,这些项目代表数据源的下一级分层结构。TreeViewItemBreadcrumbItem 之间的区别在于,BreadcrumbItem 只显示选定的项,而 TreeViewItem 显示所有项。

由于标题是一个视觉元素,不一定能转换为字符串,因此 Trace 属性用于从所有选定的 BreadcrumbItem 构建 BreadcrumbBarPath,反之亦然。Trace 的类型是 object;因此,可以分配字符串,也可以分配 XmlNode。如果你想将值检索为字符串,可以使用 TrailValue 属性。

Image 属性指定了将在 BreadcrumbBar 中为选定项显示的图像 ImageSource,以及在 BreadcrumbItem 的下拉菜单上显示的图像。

注意:由于图像可以在 BreadcrumbBar 和下拉菜单上显示,所以它不能是一个 Image 控件,因为一个控件只能有一个父级。

BreadcrumbButton

一个 HeaderedItemsControl,它打开一个下拉菜单以选择下一个面包屑项。

注意BreadcrumbButtonBreadcrumbItem 的一部分的辅助控件,不应直接使用。

重要的依赖属性

  • BreadcrumbBar.Root 指定第一个面包屑项。这可以是一个 BreadcrumbItem,也可以是一个分层数据源。
  • BreadcrumbBar.Path 获取或设置 BreadcrumbBar 的路径。
  • BreadcrumbBar.SelectedItem 获取选定的数据项或 BreadcrumbItem
  • BreadcrumbBar.SelectedBreadcrumb 获取选定的(虚拟)BreadcrumbItem
  • BreadcrumbBar.TraceBinding 获取或设置 BreadcrumbBarPath,该路径由每个选定的项表示,从根项开始。
  • 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>

也可以不使用 TraceBindingImageBinding 来绑定 TraceImage 属性,如下例所示,但使用 TraceBindingImageBinding 可以使 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>

按需填充面包屑项

以下代码段演示了如何使用 BreadcrumbBarPopulateItems 事件按需填充面包屑项。如果您无法或不想在数据源中指定所有可能的层级结构,例如,当您想使用面包屑导航栏来选择文件路径时,这很有用。因此,BreadcrumbBar 有一个名为 PopulateItemsRoutedEvent,当 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

但是,比起显示为 Desktop/Network/Computer A,更希望显示为 \\Computer A。

为此,有一个名为 PathConversionRoutedEvent,它允许您使用代码在数据结构和路径之间进行转换。以下代码段显示了 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 - 发布初始版本。
© . All rights reserved.