![]() |
Platforms, Frameworks & Libraries »
Windows Presentation Foundation »
Controls
Intermediate
License: The Code Project Open License (CPOL)
XPlorerBar: A WPF Windows XP Style Explorer Bar ControlBy Olivier SimonA fully customizable WPF implementation of the left side pane that was introduced in Windows XP's Explorer. |
C#3.0.NET3.0, XAML, WPF, Architect, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
XPlorerBar is a WPF implementation of the left side pane that was introduced in Windows XP's explorer. It provides a visually attractive and versatile way to present a grouped list of options while making effective use of screen space; common usage scenarios would include providing access to multiple areas of an application or presenting multiple pages of information.
Although there are many versions of this control for Windows Forms, its implementation for WPF is rather rare and, most of the time, paying. So, as I was looking for a good idea to deepen my learning WPF, I decided to write one myself as a learning exercise.
To see the XPlorerBar in action, download the demo executable and give it a try!
FrameworkElement object (for more information, see Registering and Applying a Custom Theme).XPlorerBar class so that it is bindable (for more information see Building an XPlorerBar with Bindings).The demo application, which can be downloaded at the top of this article, allows:
XPlorerBar located on the left [A], 
Ease of use - The naming of components, methods, properties and events is consistent with the framework naming rules.
Fully customizable - All the elements (brushes, controls, geometries, animations duration, ...) are fully customizable: merge with the XPlorerBar.Generic.xaml dictionary and redefine the styles and/or templates of the items you want to customize.
Accurate look & feel - Colors and sizes of all the elements match exactly (thanks to the GIMP [^]) with the real Windows themes: 7 built-in themes are included for Vista, XP and NT.
Fully documented - As I would like this project to be helpful to the devs, the source code is highly commented and the library's API is provided as an MSDN style documentation file.
XPlorerBar hosts a vertical stack of sections, called XPlorerSection. XPlorerSection contains a fixed header and an expandable/collapsible content. XPlorerSection header can host a large icon and its associated text. If the text cannot be fully displayed, it is cropped to the header width and an ellipsis is added to indicate that cropping has occurred. XPlorerSection contents can be expanded or collapsed by clicking on their headers. XPlorerSection uses animations when its content is being expanded (fade in and slide down) or collapsed (fade out and slide up). Remark: animation durations have to be customizable by the user. XPlorerSection can host any sort of content, an XPlorerItem component is provided to easily display a text with its small icon, add hot tracking and a 'Click' event to the command. XPlorerItem cannot be fully displayed, its text is wrapped to the header width and ends on the next line. XPlorerSection can be designated as 'Primary' to be displayed differently than 'normal' sections. XPlorerBar elements (brushes, controls, geometries, ...) have to be easily accessible to the user. XPlorerBar. XPlorerBar, it automatically obtains its colors from the active Windows theme. The XPlorerBar control and its associated elements are located in the ZonaTools.XPlorerBar namespace. Make sure you add a reference to the compiled library ZonaTools.XPlorerBar.dll before using it.
The image below identifies key parts of XPlorerBar control:

XPlorerSection[Primary]Header[Hover]ForegroundBrush XPlorerSection[Primary]HeaderBackgroundBrush XPlorerSection button are:
XPlorerSection[Primary]HeaderButtonBackgroundBrush XPlorerSection[Primary]HeaderButton[Hover]ForegroundBrush XPlorerSection[Primary]HeaderButtonBorderBrush XPlorerSectionHeaderExpandArrows XPlorerSectionHeaderCollapseArrows XPlorerBarBackgroundBrush XPlorerSection[Primary]Content[Hover]ForegroundBrush XPlorerSection[Primary]ContentBackgroundBrush XPlorerSection[Primary]ContentBorderBrush Remark: the words inside of square brackets are optional:
XPlorerSection is set as 'Primary' (e.g. XPlorerSectionPrimaryContentBorderBrush). XPlorerSectionHeaderHoverForegroundBrush). All the above elements can be reused in your own templates.
The sample code below shows how to assign the background brush of the active XPlorerBar theme to the Background property of an element:
xmlns:xpbar="clr-namespace:ZonaTools.XPlorerBar;assembly=ZonaTools.XPlorerBar"
...
<Setter Property="Background"
Value=
"{DynamicResource
{x:Static xpbar:XPlorerResourceKeys.XPlorerBarBackgroundBrushKey}}"/>
Remark 1: The role of the XPlorerResourceKeys class is explained later in this article.
Remark 2: The name of the static ComponentResourceKey to use when accessing an XPlorerBar element is simply the element name (as shown above) with the Key suffix.
This sample shows how to create an XPlorerBar with two XPlorerSection and a few XPlorerItem. The first XPlorerSection is set as 'Primary' and the XPlorerBar theme is set to the silver Windows XP theme:
xmlns:xpbar="clr-namespace:ZonaTools.XPlorerBar;assembly=ZonaTools.XPlorerBar"
...
<!-- XPlorerBar -->
<xpbar:XPlorerBar x:Name="ZT_XPlorerBar"
xpbar:ThemeManager.Theme="LunaSilver"
AllowMultipleExpands="True">
<!-- Music Tasks -->
<xpbar:XPlorerSection Header="Music Tasks"
HeaderImage="/Images/MyMusic32.png"
IsExpanded="True" IsPrimary="True">
<StackPanel Orientation="Vertical">
<xpbar:XPlorerItem ItemText="Play all"
ItemImage="/Images/PlayAll16.png"
Click="XPlorerItem_Click" />
<xpbar:XPlorerItem ItemText="Shop for music online"
ItemImage="/Images/MusicOnLine16.png"
Click="XPlorerItem_Click" />
</StackPanel>
</xpbar:XPlorerSection>
<!-- File and Folder Tasks -->
<xpbar:XPlorerSection Header="File and Folder Tasks"
IsExpanded="True" IsPrimary="False">
<StackPanel Orientation="Vertical">
<xpbar:XPlorerItem ItemText="Rename this file"
ItemImage="/Images/Rename16.png"
Click="XPlorerItem_Click" />
<xpbar:XPlorerItem ItemText="Move this file"
ItemImage="/Images/Move16.png"
Click="XPlorerItem_Click" />
<xpbar:XPlorerItem ItemText="Copy this file"
ItemImage="/Images/Copy16.png"
Click="XPlorerItem_Click" />
<xpbar:XPlorerItem ItemText="E-mail this file"
ItemImage="/Images/MailFile16.png"
Click="XPlorerItem_Click" />
<xpbar:XPlorerItem ItemText="Delete this file"
ItemImage="/Images/Delete16.png"
Click="XPlorerItem_Click" />
</StackPanel>
</xpbar:XPlorerSection>
</xpbar:XPlorerBar>
In the code-behind file, the Click event is handled as follows:
private void XPlorerItem_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(
string.Format("You clicked the '{0}' item.",
((XPlorerItem)e.OriginalSource).ItemText));
}
The result is shown below:
To extend the visual appearance of your XPlorerBar, you can create your own theme dictionaries.
The procedure for creating a new theme dictionary is quite simple: in most cases, you will merge with the XPlorerBar.Generic.xaml dictionary, override one or more elements (brushes, geometries, styles, templates, ...) and add it to your project, as shown below:
Then, you need to create your Theme object as follows:
Theme codeProjectTheme = new Theme(
"CodeProject theme",
"ZonaTools.XPlorerBar.DemoApp;component/Skins/CodeProjectSkinDictionary.xaml");
And finally, your new theme has to be registered for XPlorerBar objects as shown below:
ThemeManager.RegisterTheme(codeProjectTheme, typeof(XPlorerBar));
You can now use your theme whenever you want by setting (in XAML) the ThemeManager.Theme to the registered name of your theme...
ThemeManager.Theme = "CodeProject theme"
... or, in the code-behind file:
ZT_XPlorerBar.SetValue(ThemeManager.ThemeProperty, "CodeProject theme");
With your custom theme applied, the preceding example becomes:
Remark: As you have seen earlier, the themes can now be applied to any FrameworkElement object. To do so, all you have to do is to register the desired theme to the type of object you want to see themed and apply it to the proper instance. An example is provided in the Extra_ThemeManagement folder: to run this example, modify the App.xaml file of the XPlorerBar.DemoApp project as follows:
StartupUri = "Extra_ThemeManagement/ThemesWindow.xaml"
As you have seen so far, it's really simple to "tune" an existing theme, register it in the ThemeManager and use it in your application. But what if you want to completely redefine an element like an XPlorerSection? How will you restyle the control without modifying or replacing expected behavior?
The answer to the last question is: With Template Parts' help.
The Template Parts allow the configuration of all the binding expressions in the initialization code of the control itself and, this way, the template doesn't need to specify these details anymore. All you have to do then, is to focus on the appearance of your control.
As you have already seen, an XPlorerSection is made up of a header and a content or, from the visual tree point of view, of a ToggleButton and an XPandableDecorator. Two Template Parts are defined in the XPlorerSection class:
PART_HeaderSite (on the ToggleButton), keeps the ToggleButton.IsChecked dependency property synchronized with the XPlorerSection.IsExpanded dependency property. PART_ContentSite (on the XPandableDecorator), does the same between the XPandableDecorator and the XPlorerSection. The sample code below shows how the two Template Parts are used in an XPlorerSection control template:
...
<StackPanel Orientation="Vertical">
<!-- Header -->
<ToggleButton x:Name="Part_HeaderSite"
Content="{TemplateBinding Header}"
Style="{StaticResource HeaderStyle}"/>
<!-- Content -->
<xpbar:XPandableDecorator x:Name="PART_ContentSite">
<Border Background="{TemplateBinding Background}"
CornerRadius="0,0,4,4">
<ContentPresenter Margin="{TemplateBinding Padding}"/>
</Border>
</xpbar:XPandableDecorator>
</StackPanel>
...
Remark: if you want to see how the two Template Parts are defined, have a look at the OnApplyTemplate method of the XPlorerSection class.
One of the major new features of the library is that the XPlorerBar is now bindable. Indeed, it's now possible to build dynamically an XPlorerBar with bindings to a data source as an XML file or a collection of observable objects. An example is provided in the Extra_BindingMode folder: to run this example, modify the App.xaml of the XPlorerBar.DemoApp project as follows:
StartupUri = "Extra_BindingMode/BindingsWindow.xaml"
In this example, the data source is an XML file (XPlorerBarXMLFile.xml) presented as shown below:
<?xml version="1.0" encoding="utf-8"?>
<XPlorerBarData>
<!-- Music Tasks -->
<XPlorerSectionData Header="Music Tasks"
HeaderImage="/Images/MyMusic32.png" IsPrimary="True">
<XPlorerItemData ItemText="Play all" ItemImage="/Images/PlayAll16.png"/>
<XPlorerItemData ItemText="Shop for music online"
ItemImage="/Images/MusicOnLine16.png"/>
</XPlorerSectionData>
...
The Window.Resources part of the BindingsWindow.xaml file contains the XML data provider and the data templates used to retrieve and organize the data from the XML file:
...
<!-- Data provider -->
<XmlDataProvider x:Key="ZT_XPlorerBarData"
Source="XPlorerBarXMLFile.xml" XPath="XPlorerBarData"/>
<!-- Data templates -->
<DataTemplate x:Key="itemTemplate">
<xpbar:XPlorerItem ItemText="{Binding XPath=@ItemText}"
ItemImage="{Binding XPath=@ItemImage}"
Click="XPlorerItem_Click"/>
</DataTemplate>
<HierarchicalDataTemplate x:Key="sectionTemplate" DataType="XPlorerSectionData">
<xpbar:XPlorerSection Header="{Binding XPath=@Header}"
HeaderImage="{Binding XPath=@HeaderImage}"
IsExpanded="True" IsPrimary="{Binding XPath=@IsPrimary}">
<xpbar:XPlorerSection.Content>
<ItemsControl ItemsSource="{Binding XPath=./XPlorerItemData}"
ItemTemplate="{StaticResource itemTemplate}"/>
</xpbar:XPlorerSection.Content>
</xpbar:XPlorerSection>
</HierarchicalDataTemplate>
...
Finally, the XPlorerBar is declared as follows:
<!-- XPlorerBar -->
<xpbar:XPlorerBar x:Name="ZT_XPlorerBar" xpbar:ThemeManager.Theme="LunaBlue"
VerticalAlignment="Stretch" Width="Auto" AllowMultipleExpands="False"
ItemsSource="{Binding Source={StaticResource ZT_XPlorerBarData},
XPath=XPlorerSectionData}"
ItemTemplate="{StaticResource sectionTemplate}"/>
The result is shown below:
9 themes are provided with this project :
Enumerated from left to right:
| Theme | File | Registered name | |
| -- Built-in themes -- | |||
| Windows Vista theme | themes/Aero.NormalColor.xaml | Aero |
|
| Windows Classic theme | themes/Classic.xaml | Classic |
|
| Default Windows XP theme | themes/Luna.NormalColor.xaml | LunaBlue |
|
| Olive green Windows XP theme | themes/Luna.Homestead.xaml | LunaOliveGreen |
|
| Silver Windows XP theme | themes/Luna.Metallic.xaml | LunaSilver |
|
| Windows XP Media Center Edition theme | themes/Royale.NormalColor.xaml | Royale |
|
| Zune Windows XP theme | themes/Zune.NormalColor.xaml | Zune |
|
| Expression Blend theme | themes/BlendDictionary.xaml | Blend |
|
| -- Custom theme -- | |||
| Code Project theme | skins/CodeProjectSkinDictionary.xaml | CodeProject theme |
|
Remark: The first seven built-in themes enable your XPlorerBar to adapt to the current operating system theme (only if no specific theme is applied to the XPlorerBar or if the ThemeManager.Theme is set to Default).
Here is the library project structure, as seen in Visual Studio's Solution Explorer:
The role of the library classes is explained below:
ThemeManager static class is used for new themes registration and current theme switching. XPandableDecorator class defines the animations used to expand or collapse its content. Inspired by Kevin Moore's Reveal control (from its Bag-o-Tricks [^]), this control has then been adapted to support theming and skinning. XPlorerBar class implements the features and the behavior of an XPlorerBar control. An XPlorerBar can only contain XPlorerSection. XPlorerItem class implements the features and the behavior of any XPlorerItem nested in an XPlorerSection. An XPlorerItem can contain a text and/or a small icon. XPlorerResourceKeys static class defines a static ComponentResourceKey name for each resource we plan to share with another assembly. XPlorerSection class implements the features and the behavior of any section of an XPlorerBar. An XPlorerSection can contain any sort of content as well in its header as in its content. However, two properties allow to easily set its header text and its header large icon. The Documents folder, reminds you the history of the current release and gives you an overview of the tests executed on the library.
The goal of this quick presentation of the role of the main classes of the ZonaTools.XPlorerBar library is to give you a guide to easily navigate in the source code.
The API's documentation will give you more details on the members of each class of the library.
Finally, the many comments in the source code should give you the keys to quickly understand what is done.
The API's documentation was generated with Sandcastle [^] used in combination with Sandcastle Help File Builder [^] (SHFB).
The SHFB project (XPlorerBarDocumentationProject.shfb in the XPlorerBar.Documentation folder) is set to generate a MSDN-like document as an HTML Help 1 file (*.chm).
The documentation project also permits the generation of the documentation as an HTML Help 2 file (*.hxs) or as a Web site (all you need to do is change the 'HelpFileFormat' parameter as shown below and rebuild).
The project was developed with the following tools:
This is my first article on The Code Project. So, please let me know what you think.
I hope you'll find this article helpful and instructive. However, if my approach is totally wrong also feel free to let me know.
I definitely want to hear what the community thinks.
FrameworkElement object. This class replaces the previous ThemeManager class.ThemeDictionary class.XPlorerBar class so that an XPlorerBar can now be built dynamically with bindings to a data source.ExpandableDecorator class in XPandableDecorator.
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 9 Dec 2008 Editor: Deeksha Shenoy |
Copyright 2008 by Olivier Simon Everything else Copyright © CodeProject, 1999-2010 Web18 | Advertise on the Code Project |