Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

XPlorerBar: A WPF Windows XP Style Explorer Bar Control

, 9 Dec 2008
A fully customizable WPF implementation of the left side pane that was introduced in Windows XP's Explorer.
XPlorerBar_demo.zip
XPlorerBar_demo
ZonaTools.XPlorerBar.DemoApp.exe
ZonaTools.XPlorerBar.dll
ZonaTools.XPlorerBar.Documentation.chm
XPlorerBar_src.zip
XPlorerBar_src
XPlorerBar.DemoApp
Converters
Extra_BindingMode
Extra_ThemeManagement
Images
codeproject120x60.gif
Computer16.png
Copy16.png
CreateFolder16.png
Delete16.png
MailFile16.png
Move16.png
MusicOnLine16.png
MyComputer16.png
MyDocuments16.png
MyMusic32.png
MyNetwork16.png
MyPictures16.png
MyPictures32.png
MyPictures48.png
NetworkFavorites16.png
OrderPictures16.png
PlayAll16.png
PrintPictures16.png
PublishFolder16.png
Rename16.png
SharedMusic16.png
ShareFolder16.png
SlideShow16.png
Properties
Settings.settings
Resources
Images
Folder16.png
MyComputer16.png
NetworkPlaces16.png
PicturePrint16.png
PictureTasks32.png
PictureTasksMono48.png
PrintsOnline16.png
SlideShow16.png
Skins
XPlorerBar.DemoApp.suo
XPlorerBar.Documentation
Help
Documentation.chm
LastBuild.log
XPlorerBarDocumentationProject.shfb
XPlorerBar.Library
Converters
Documents
ReleaseHistory.pdf
TestPlan.pdf
Implementation
Properties
Settings.settings
Themes
#region [       Copyright © 2008, Zona-Tools, all rights reserved.       ]
/*
 * 
    This source code is licensed under the Code Project Open License (CPOL).
    Check out http://www.codeproject.com/info/cpol10.aspx for further details.
 * 
*/
#endregion


#region [       Using namespaces       ]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

#endregion


namespace ZonaTools.XPlorerBar
{
    #region [       Theme definition structure       ]

    /// <summary>
    /// Represents a theme with its name and the path to its resource dictionary.
    /// </summary>
    public struct Theme
    {
        /// <summary>
        /// Name of the theme.
        /// </summary>
        public string Name;
        /// <summary>
        /// Path of the theme resource dictionary.
        /// </summary>
        public string DictionaryPath;

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="name">Name of the theme.</param>
        /// <param name="dictionaryPath">Path of the theme resource dictionary.</param>
        public Theme(string name, string dictionaryPath)
        {
            Name = name;
            DictionaryPath = dictionaryPath;
        }
    }

    #endregion


    #region [       Theme names enumeration       ]

    /// <summary>
    /// Specifies the names of the most common themes.
    /// </summary>
    public enum Themes
    {
        /// <summary>
        /// Name used to unload the themes of an element.
        /// </summary>
        Default,
        /// <summary>
        /// Name of the Aero.NormalColor theme.
        /// </summary>
        Aero,
        /// <summary>
        /// Name of the Classic theme.
        /// </summary>
        Classic,
        /// <summary>
        /// Name of the Luna.NormalColor theme.
        /// </summary>
        LunaBlue,
        /// <summary>
        /// Name of the Luna.Homestead theme.
        /// </summary>
        LunaOliveGreen,
        /// <summary>
        /// Name of the Luna.Metallic theme.
        /// </summary>
        LunaSilver,
        /// <summary>
        /// Name of the Royale.NormalColor theme.
        /// </summary>
        Royale,
        /// <summary>
        /// Name of the Zune.NormalColor theme.
        /// </summary>
        Zune,
        /// <summary>
        /// Name of the Blend theme.
        /// </summary>
        Blend
    };
    
    #endregion


    /// <summary>
    /// Manages the themes used by any <c>FrameworkElement</c>.
    /// </summary>
    public static class ThemeManager
    {
        #region [       String definitions       ]

        private const string Lang_Caption =
            "Theme Management";
        private const string Lang_ChangeThemeToPb =
            "Unable to change the current theme because the '{0}' theme is not registered for the '{1}' objects.";
        private const string Lang_RegisterThemePb =
            "Unable to register the '{0}' theme for the '{1}' objects.";

        #endregion


        #region [       Fields       ]

        /// <summary>
        /// Represents the collection of all the registered themes.
        /// </summary>
        /// <remarks>
        /// The key of this dictionary represents the name used to register a theme.
        /// </remarks>
        private static Dictionary<string, ResourceDictionary>
            _registeredDictionaries = new Dictionary<string, ResourceDictionary>();

        #endregion


        #region [       Dependency properties       ]

        #region Theme attached property

        //===========================================================================
        /// <summary>
        /// Identifies the <c>Theme</c> attached property.
        /// </summary>
        /// <remarks>The default value is <c>Default</c>.</remarks>
        //===========================================================================
        public static readonly DependencyProperty ThemeProperty =
            DependencyProperty.RegisterAttached("Theme", 
            typeof(string), typeof(ThemeManager),
                new FrameworkPropertyMetadata(Themes.Default.ToString(),
                    FrameworkPropertyMetadataOptions.None,
                    new PropertyChangedCallback(OnThemeChanged)));

        /// <summary>
        /// Gets the value of the <c>Theme</c> attached property for a 
        /// specified <c>FrameworkElement</c>.
        /// </summary>
        [Category(XPlorerBar.CATEGORYNAME), AttachedPropertyBrowsableForType(typeof(FrameworkElement))]
        public static string GetTheme(DependencyObject d)
        {
            if (d == null)
                throw new ArgumentNullException("d");
            return (string)d.GetValue(ThemeProperty);
        }

        /// <summary>
        /// Sets the value of the <c>Theme</c> attached property to a 
        /// specified <c>FrameworkElement</c>.
        /// </summary>
        public static void SetTheme(DependencyObject d, string value)
        {
            if (d == null)
                throw new ArgumentNullException("d");
            d.SetValue(ThemeProperty, value);
        }

        /// <summary>
        /// Invoked whenever the <c>Theme</c> attached property value has 
        /// been updated.
        /// </summary>
        /// <param name="d">The <c>DependencyObject</c> on which the property has 
        /// changed value.</param>
        /// <param name="e">Event data that is issued by any event that tracks changes 
        /// to the effective value of this property.</param>
        private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //Gets the element on which apply the new theme
            FrameworkElement element = d as FrameworkElement;

            //Makes sure the arguments are valid
            if (element == null)
                throw new ArgumentNullException("d");
            if (e == null)
                throw new ArgumentNullException("e");

            //-------------------------------------------------------------
            //Removes the current theme dictionary from element's resources
            //-------------------------------------------------------------

            //Gets the name of the current theme
            string curThemeName = e.OldValue as string;

            //If the current theme is the default theme, there's nothing to remove
            if (!curThemeName.Equals(Themes.Default.ToString()))
            {
                //Gets the registered name of the current theme
                string curRegisteredThemeName = 
                    GetRegistrationName(curThemeName, element.GetType());

                //If the current theme is registered
                if (_registeredDictionaries.ContainsKey(curRegisteredThemeName))
                {
                    //Gets the resource dictionary of the current theme
                    ResourceDictionary curThemeDictionary =
                        _registeredDictionaries[curRegisteredThemeName];
                    //and removes it
                    element.Resources.MergedDictionaries.Remove(curThemeDictionary);
                }
            }

            //----------------------------------------------------
            //Adds the new theme dictionary to element's resources
            //----------------------------------------------------

            //Gets the name of the new theme
            string newThemeName = e.NewValue as string;

            //If the new theme is the default theme, there's nothing to add
            if (!newThemeName.Equals(Themes.Default.ToString()))
            {
                //Gets the registered name of the new theme
                string newRegisteredThemeName =
                    GetRegistrationName(newThemeName, element.GetType());

                //If the new theme is not registered
                if (!_registeredDictionaries.ContainsKey(newRegisteredThemeName))
                {
                    //Displays an error message
                    MessageBox.Show(
                        string.Format(Lang_ChangeThemeToPb, newThemeName, element.GetType().ToString()),
                        Lang_Caption, MessageBoxButton.OK, MessageBoxImage.Warning);
                }
                else
                {
                    //Gets the resource dictionary of the new theme
                    ResourceDictionary newThemeDictionary =
                        _registeredDictionaries[newRegisteredThemeName];
                    //and applies it to the source element
                    element.Resources.MergedDictionaries.Add(newThemeDictionary);
                }
            }
        }

        #endregion

        #endregion


        #region [       Registers a new theme       ]

        //===========================================================================
        /// <summary>
        /// Registers a new theme with a specified name and a specified <c>Uri</c>.
        /// </summary>
        /// <param name="theme">Theme to register.</param>
        /// <param name="ownerType">The owner type that is registering the theme.
        /// </param>
        //===========================================================================
        public static void RegisterTheme(Theme theme, Type ownerType)
        {
            //Makes sure the arguments are valid
            if ((theme.Name == null) || (theme.DictionaryPath == null))
                throw new ArgumentNullException("theme");
            if (ownerType == null)
                throw new ArgumentNullException("ownerType");

            //Gets the registration name
            string registrationName = 
                GetRegistrationName(theme.Name, ownerType);

            //Checks that the new theme is not the default theme and 
            //that it is not already registered
            if (theme.Name.Equals(Themes.Default.ToString()) ||
                _registeredDictionaries.ContainsKey(registrationName))
                return;

            try
            {
                //Creates the Uri of the specified theme
                Uri themeUri = new Uri(theme.DictionaryPath, UriKind.Relative);

                //Registers the new theme
                _registeredDictionaries[registrationName] =
                    Application.LoadComponent(themeUri) as ResourceDictionary;
            }
            catch
            {
                //Dislays an error message
                MessageBox.Show(
                    string.Format(Lang_RegisterThemePb, theme.Name, ownerType.ToString()),
                    Lang_Caption, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }


        //===========================================================================
        /// <summary>
        /// Gets the name used for the registration of the specified theme.
        /// </summary>
        /// <param name="themeName">Name of the theme to register.</param>
        /// <param name="ownerType">The owner type that is registering the theme.
        /// </param>
        /// <returns>Name used for the registration of the specified theme.</returns>
        //===========================================================================
        private static string GetRegistrationName(string themeName, Type ownerType)
        {
            //Sets the registration name (Type name;theme name)
            string registrationName =
                string.Format("{0};{1}", ownerType.ToString(), themeName);

            return registrationName;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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

Share

About the Author

Olivier Simon
Team Leader
France France
I have been developing and managing projects for real-time embedded softwares for eight years. Then, I moved from Paris to the south of France and began to lead a team who was developping Java applications.
 
My main occupation right now is to continue my journey in the WPF world.
 
You can check out my blog here. [^]

You may also be interested in...

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 9 Dec 2008
Article Copyright 2008 by Olivier Simon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid