Introduction
This article provides an implementation of a WPF Breadcrumb
control and describes how to develop one.
Background
When Vista was released, one of its main features was Breadcrumb
explorer bar, I always wanted to build one, but I was lacking the knowledge to develop one myself.
Nesher created a breadcrumb component couple of months ago, which is a fully working one, but it is an XAML intensive solution and is too complicated for me to understand the code, not to mention I want to modify it and add features, so I write my own using MVP pattern (where the model is a string
).
His implementation gave me idea of how to develop a breadcrumb, and I took a couple styles from his implementation. Besides that, my implementation is a complete rewrite, and they have a couple of differences:
- It is fully
string
based, that means
- SubFolder polling is done manually. You cannot bind a
HierarchicalDataModel
and expect it to work automatically.
- You can use two or more different "
Root
", like Folder
and Animal
in demo, this is changeable in runtime.
- Expander support, which shows when you have too many
BreadcrumbItems
on the Breadcrumb
.
- Progressbar support.
- Dropdown support, the
BreadcrumbControl
itself is a ComboBox
(ver2):
- Autocomplete textbox support
- Remember child position when changing directory, only rearrange when necessary.
How to Use?
If you want to use the component as directory Breadcrumb
only, just add the main control to your window. The main control has a bindable property named SelectedFolder
, which is a string
, you can bind it to other component, e.g.
<TextBox x:Name="tb" Text="{Binding ElementName=breadcrumb, Path=RootFolder}" />
<uc:BreadcrumbControl Margin="0,50,0,0" x:Name="breadcrumb" />
If you want to use the component to display custom data, you will have to write:
- A view, which is a
DataTemplate
,
<DataTemplate x:Key="folderDataTemplate">
<DockPanel>
-->
<Image Height="16" Width="16"
Source="{Binding Icon}" />
<TextBlock Text="{Binding DisplayName}" Margin="2,0" />
</DockPanel>
</DataTemplate>
-->
<uc:BreadcrumbControl SubItemTemplate="{StaticResource folderDataTemplate}"/>
- A presenter, which is derived from
BreadcrumbItemBase
, which implements the following: If you want to attach your model, you can attach it inside your derived presenter.
public override BreadcrumbItemBase[] PollSubFolders();
public override string ConvertPath(BreadcrumbItemBase.PathType pt, string path)
public override ImageSource GetIcon()
- Modify the
BreadcrumbControl
to support your new presenter and view.
CustomPresenter Root = new CustomPresenter();
SwitchPresenter(Root);
How It Works?
As I mentioned before, the whole thing is string
based, ItemsPresenter
returns string
as folder, folder creation is based on a folder name, that's why you have to make sure the code is legit before passing it to CurrentFolder
property in BreadcrumbControl
. (TypedPresenter
does have some kind of lookup, other implementations don't check if the folder exists).
String
based makes it easier to develop (Breadcrumb
usually uses as navigation purpose, sometimes you don't want to make a model for every navigation item), however, it restricts the amount of information to display in view, fortunately for BreadcrumbItems
, it requires only an Icon and a text, I can easily use a "Converter
" to do this work. For folder path, I used PathToDirNameConverter
, for Icon, I used a FileToIcon converter.
The diagram is as follows:
Part of the program (AutoCompleteTextBox
and BreadcrumbCore
) is designed using Model - View - Presenter design pattern, this separate UI code and Logic code and reduce complexity.
The BreadcrubCore
contains a number of components:
- A
BreadcrumbCore
- contain an expander,
- Contains one or more
BreadcrumbItems
- An
AutoCompleteTextBox
(AutoCompleteTextBox
)
- A
ProgressBar
(accessible via Progress
and IsIndeterminate
in BreadcrumbControl
)
- A number of
buttons
- A toggle button which toggles between the
AutoCompleteTextBox
and BreadcrumbCore
- A toggle button for dropdown
- A refresh button (raise
RefreshClicked
event when clicked)
AutoCompleteTextBox
The "AutoCompleteTextBox
" suggest items based on input, it will look for all items in the current folder, and display if the text is matched:
List<string> retVal = new List<string>();
foreach (BreadcrumbItemBase subFolder in _currentPresenter.ActualSubFolders)
if (subFolder.FolderPath.ToLower().StartsWith(_selectedPath.ToLower()))
retVal.Add(subFolder.FolderPath);
Suggestions = retVal.ToArray();
The BreadcrumbItem
The BreadcrumbItem
are items inside the container, it's composed of a custom BreadcrumbItemBase
(Presenter
) and a ComboBox
(View
):
BreadcrumbItemBase
is the presenter of BreadcrumbItems
, a couple of ItemsPresenter
defined in the demo:
BreadcrumbItemBase
- Base class, derive from this for define custom BreadcrumbItemBase
FolderPresenter
- Contains logic to current folder and poll subfolders
AnimalPresenter
- For test purpose only, generate cat/dog/rat combination as subfolders
The view part of BreadcrumbItems
is a styled ComboBox
, which has Items
bound to ItemPresenter
's SubFolders, the ComboBox
has the following items:
- Main button (
buttonCurrent
), which occupied most space on the ComboBox
, when user clicked on it, change to current folder. (That's why it is called button Current
)
- Toggle button (
buttonExpand
) which specifies if the Popup
is shown (I used nesher's style here)
Popup
(PART_Popup
), the popup part, it's called that way because WPF required it..
ItemsPresenter
(itemList
), located in the popup
, hold all SubFolders (string
s).
Nesher's implementation uses a context menu instead of ComboBox
, this can be easier implemented using ComboBox
, however, the default position of the Popup
in the ComboBox
Aligned Left side of the ComboBox
, one have to change the Placement
and PlacementTarget
property of the Popup
, like below:
<Popup ... Placement="Bottom" PlacementTarget="{Binding ElementName=buttonExpand}" />
And BTW, TranslateTransform
doesn't work to reposition the Popup
, e.g., the following doesn't work:
<Popup.RenderTransform>
<TranslateTransform X="150" Y="0"/>
</Popup.RenderTransform>
The Expander
is a ComboBox
with no DisplayText
and a customized Icon. When the Breadcrumb Item
s's IsHitTestVisible
is set to false
(by BreadcrumbCorePanel
), they will add themselves to the expander, and remove when reverse. In version 2, the expander is replaced with Root combobox.
public bool HitTestVisible { get { return true; }
set { changedHitTestVisible(value); } } private void changedHitTestVisible(bool value)
{
if (!value) _parentPresenter.Expander.Add(DisplayPath);
else _parentPresenter.Expander.Remove(DisplayPath);
}
The ToggleButton
is hidden if there's no item in the list.
Uncompleted Items
References
History
- 02-01-09 Initial version
- 03-01-09 Fix: Ghost folder in expander
- 03-01-09 Add: Return selected folder model (for
TypedPresenter
)
- 04-01-09 Add: Alt+D Toggle
TextBox
/Breadcrumb
- 04-01-09 Add:
Autocomplete textbox
now supports non-diskfolder types
- 04-01-09 Version 1.2
- 04-01-09 Fix: Pressing enter button in
textbox
does not switch back to breadcrumb
if the text is not changed
- 05-01-09 Update: Code clean up, assembly is created (QuickZip.UserControls.Breadcrumb.dll)
- 05-01-09 Add: The view part is moved to
BreadcrumbControl.SubItemTemplate
(See demo, article requires update)
- 05-01-09 Fix: Some update to
TypedPresenter
is added
- 05-01-09 Version 1.3
- 05-01-09 Fix: Alt+D Toggle not working correctly
- 05-01-09 Update: Select last char when toggle to
textbox
05-01-09 Add: Remember child position
- 05-01-09 Fix: Crash when suggestion changes when selection folder
- 05-01-09 Version 1.4
- 06-01-09 Fix: Ghost folder again (broken in last version)
- 06-01-09 Version 1.5
- 07-01-09 Add: QuickZip.UserControls.TypedBreadcrumb.dll, designed for Model use
- 07-01-09 ----: (Expander is not complete and autocomplete textbox not showing suggestions in some case, will be added in next version)
- 07-01-09 Update: Demo updated to reflect changes
- 07-01-09 Article update
- 07-01-09 Version 1.6
- 08-01-09 Fix:
Expander
and AutocompleteTextbox
in TypedBreadcrumb
- 08-01-09 Version 1.7
- 16-01-09 Update: Rewrite, simplified the code and added some documentation (not finished yet)
- 16-01-09 Update: Removed the expander and placed the expander logic in root (looks more like Vista's
breadcrumb
).
- 16-01-09 Add: Support folder with
null FolderName
now (e.g. Desktop\Computer)
- 16-01-09 Add: Support Adding Custom folder to expander list now (see
IRoot
interface in IExpander.cs, or the demo)
- 16-01-09 Add: Support Adding Separator to expander list
- 16-01-09 Version 2.1
- 16-01-09 Article updated
- 16-01-09 Add: Refresh button
- 16-01-09 Add: History dropdown
- 16-01-09 Fix: Splitter width
- 16-01-09 Update: Display Root caption when no items are selected
- 17-01-09 Fix:
IsTextBoxEnabled
is now working
- 17-01-09 Version 2.2
- 17-01-09 Fix:
DropDown SelectedIndex
not reset when opened
- 18-01-09 Add:
RefreshCommand
/Parameter
/Target
- 18-01-09 Update: Documentation of BreadcrumbItemBase.cs
- 18-01-09 Version 2.3
- 20-01-09 Update: Better
DataBinding
support
- 22-01-09 Add: Animation when root folder resizing, change folder
- 22-01-09 Version 2.4
- 23-01-09 Fix: Adding folder to expander (internally) will change root selected index, and lead to unintended folder change
- 23-01-09 Version 2.5