Click here to Skip to main content
Click here to Skip to main content

WPF BreadcrumbBar

, 3 Oct 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
A WPF BreadcrumbBar implementation.

Introduction

This is a Vista like breadcrumb bar for WPF that supports HierarchicalTemplates, population on demand, dynamic path conversation, and many more.

Background

The BreadcrumbBar is part of a free WPF control library named Odyssey that I'm currently developing just for fun. It is similar to the Vista breadcrumb bar, hence it is actually a multi-control bar consisting of the breadcrumb part, an editable ComboBox, a progress bar, and a button area.

The BreadcrumbBar is a control to display hierarchical data sources. The hierarchy is described by a HierarchicalDataTemplate the same way as for a TreeView control. The BreadcrumbBar contains only one BreadcrumbItem, which is the Root property. Root can be assigned directly to a BreadcrumbItem by XAML or code, or to a hierarchical data source. In the latter case, virtual BreadcrumbItems are built automatically, and the root BreadcrumbItem can be accessed by the RootItem property. In contrast to a TreeView, the BreadcrumbBar can have only one root item.

BreadcrumbItem

A HeaderedItemsControl that contains a collection of items which represent the next hierarchy of the data source. The difference between TreeViewItem and BreadcrumbItem is that the BreadcrumbItem displays only the selected item, whereas the TreeViewItem displays all items.

Since the header is a visual that not necessarily can be converted to a string, the Trace property is used to build the Path for the BreadcrumbBar from all the selected BreadcrumbItems, and vice versa. Trace is of type object; therefore, it is possible to assign not only a string but also an XmlNode. If you want to retrieve the value as a string, you can use the TrailValue property.

The Image property specifies the ImageSource for the item to be displayed at the BreadcrumbBar for the selected item and on the dropdown menu on a BreadcrumbItem.

Note: Since it is possible to display the image on the BreadcrumbBar and a dropdown menu, it cannot be an Image control as a control can only have one parent.

BreadcrumbButton

A HeaderedItemsControl that opens a drop down menu to select the next breadcrumb.

Note: BreadcrumbButton is a helper control which is part of BreadcrumbItem and should not be used directly.

Important dependency properties

  • BreadcrumbBar.Root specifies the first breadcrumb. This can be either a BreadcrumbItem or a hierarchical data source.
  • BreadcrumbBar.Path gets or sets the path of the BreadcrumbBar.
  • BreadcrumbBar.SelectedItem gets the selected data item or BreadcrumbItem.
  • BreadcrumbBar.SelectedBreadcrumb gets the selected (virtual) BreadcrumbItem.
  • BreadcrumbBar.TraceBinding gets or sets the Path of the BreadcrumbBar, which is presented by each selected item, beginning by the root.
  • BreadcrumbBar.ImageBinding specifies a binding to an item that presents the Image property for a BreadcrumbItem in conjunction with a data source.
  • BreadcrumbItem.Trace gets or sets the Trace property required to build the path.
  • BreadcrumbItem.Image gets or sets the Image property that is used to get the image for the BreadcrumbBar and each item in the drop down menu.

Using the code

This is an example of how to describe a BreadcrumbBar in XAML and assign nested BreadcrumbItems to the Root property:

<odc:BreadcrumbBar x:Name="bar" 
    Path="Computer\C:\"br>    PopulateItems="BreadcrumbBar_PopulateItems" 
     TraceBinding="{Binding Folder}"
    ImageBinding="{Binding Image}"
    PathConversion="BreadcrumbBar_PathConversion">

The following example shows how to use a data source to obtain the breadcrumbs, and how to bind the Trace property for each virtual BreadcrumbItem using the TraceBinding property:

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

It would also be possible to bind the Trace and Image properties without TraceBinding and ImageBinding, as shown in the following example, but using TraceBinding and ImageBinding enables easier XAML code:

<odc:BreadcrumbBar>
 <odc:BreadcrumbBar.Style>
    <Style TargetType="{x:Type odc:BreadcrumbItem}">
        <Setter Property="Trace" Value="{Binding XPath=@title}"/>
    </Style>
</odc:BreadcrumbBar.Style>
</odc:BreacrumbBar>

Populate breadcrumbs on demand

The following snippet demonstrates how to populate breadcrumbs on demand, using the PopulateItems event of the BreadcrumbBar. This is useful if you cannot, or don't want to specify all possible hierarchies in a data source; for instance, if you want to use the breadcrumb bar to select a file path. Therefore, the BreadcrumbBar has a RoutedEvent named PopulateItems which occurs as soon as a BreadcrumbItem needs to access its items:

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

Path Conversion

Path conversion is used to parse the hierarchical structure from the text in the edit box, and vice versa. For instance, a data source has the following structure:

  • Desktop
    • Computer
      • C:
        • Windows
        • Program Files
      • D:
        • Network
          • Computer A
          • Computer B

But, instead of displaying the path as Desktop/Network/Computer A, it is preferred to show \\Computer A instead.

For that purpose, there is a RoutedEvent available, named PathConversion, that allows you to use code to convert between the data structure and the path. The following snippet shows an excerpt from the FileBrowserDemo (it's not very elegant code, I need to admit, but it demonstrates how to use it):

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

Points of interests

For more information and updates, visit my web site.

History

  • 2008-09-15 - Initial release published.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Thomas Gerber
Software Developer (Senior)
Germany Germany
MCPD
Enterprise Application Developer 3.5
Windows Developer 3.5
.ASP.NET Developer 3.5
.NET 2.0 Windows Developer
.NET 2.0 Web Developer
.NET 2.0 Enterprise Application Developer
 

MCTS
.NET 3.5 Windows Forms Applications
.NET 3.5 ASP.NET Applications
.NET 3.5, ADO.NET Application Development
.NET 3.5 WCF
.NET 3.5 WPF
.NET 3.5 WF
Microsoft SQL Server 2008, Database Development
.NET 2.0 Windows Applications
.NET 2.0 Web Applications
.NET 2.0 Distributed Applications
SQL Server 2005
Sharepoint Services 3.0 Application Development
Windows Vista Client Configuration

Comments and Discussions

 
QuestionEdit Option PinmemberMember 19378065-Aug-14 2:13 
QuestionDropDownItemTemplate Does not Work PinmemberMember 788506228-Mar-13 4:31 
QuestionCould you provide any soluation for System.Window.Text.TextBlock problem?? [modified] Pinmemberandyyu092028-Nov-12 19:40 
AnswerRe: Could you provide any soluation for System.Window.Text.TextBlock problem?? Pinmemberandyyu092029-Nov-12 16:43 
QuestionSetting Selected Item or Path PinmemberAnon87623-Aug-12 8:03 
GeneralRed text? PinmemberMember 29381754-Jul-12 6:32 
GeneralRe: Red text? PinmemberCocoaJason4-Jul-12 10:23 
Questionwinforms PinmemberZapss13-Feb-12 23:31 
GeneralMy vote of 5 PinmemberFilip D'haene17-Sep-11 3:50 
GeneralGreat control + quick question PinmemberDaniel Larocque14-Dec-10 4:41 
GeneralMy vote of 5 PinmemberAshley Davis29-Nov-10 2:40 
GeneralThanks PinmemberMember 427160326-May-10 3:25 
AnswerItemsSource Property change bug. PinmemberTri Q Tran22-Mar-10 0:34 
GeneralRe: ItemsSource Property change bug. Pinmemberjjangli25-Dec-11 0:47 
Thank you for this!! Solved my exact problem! Big Grin | :-D
GeneralPath not working! PinmemberFrederik W. Johansen6-Feb-10 0:18 
GeneralRe: Path not working! Pinmemberevchenic24-Mar-10 3:52 
GeneralRe: Path not working! PinmemberFrederik W. Johansen11-May-10 22:31 
GeneralRe: Path not working! PinmemberMember 97538154-Feb-13 2:06 
GeneralHideRootNode does not work PinmemberJOezkan11-Jan-10 23:21 
GeneralTemplate modifications Pinmemberwsnigga11-Mar-09 23:26 
GeneralSystem.Window.Text.TextBlock Showing on root drop down PinmemberThedurk29-Jan-09 9:35 
GeneralBug: Underscores in the BreadcrumbItem.Header [modified] Pinmemberbigbigllama9-Jan-09 1:35 
AnswerRe: Bug: Underscores in the BreadcrumbItem.Header PinmemberThomas Gerber14-Jan-09 12:09 
GeneralGreat Article... PinmemberYogesh Jagota19-Nov-08 3:44 
GeneralNice Pinmembersonofdaedalus1-Oct-08 6:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 3 Oct 2008
Article Copyright 2008 by Thomas Gerber
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid