How to allow full customization with a Resource Dictionary? (Part I)

This is a problem that I’ve been dealing with for the past year, and I’ve found several ways to simplify the task, but I must say that the secret is binding and commands on custom controls!

The Problem:

Last year when I started planning for the Imokapa Slideshow (you can see three images of it in the first edition of the Portuguese Official Windows Vista Magazine, I’ll post about it soon) I was told that our costumers most of the time demand a product that has their image. With this in mind, I had to create a solution that could easily be customized to fit needs of our costumers.

The Path:

In the beginning I started by creating a small Resource Dictionary that would store control positioning, colors, brushes, templates and styles. At the time the solution seemed good, but somewhat limited because I had all the controls specified in each window of the application and had them in a grid to take care of the layout. This way I couldn’t swap objects, change positioning easily or even if I wanted to make a Slider behave like a Scrollbar the only chance I would have was to create a template for the slider to make it look like a Scrollbar.

The solution:

This is what I’ll be explaining you in this first post and the next two or three.

First we need to create a small object to take care of the theme switching for us.
In the FileSystem we’ll have a Folder called “Themes”, this folder will store all images, the ResourceDictionary and other resources for each Theme in it’s separate folder. So, let’s see what we got there!

public static List<string> GetThemes()

{

    List<string> themeNames = new List<string>();

    foreach (string dir in Directory.GetDirectories("Themes"))

    {

        DirectoryInfo directory = new DirectoryInfo(dir);

        if (directory.Attributes != FileAttributes.Hidden)

            themeNames.Add(directory.Name);

    }

    return themeNames;

}

So, now we have some strings with the name of each Theme. This portion of code is really simple, it just checks for the name of all directories that aren’t hidden in the Themes Folder.
Now, for the cool stuff! Let’s Pick the Theme we like!

public static void ChangeTheme(string themeName)

{

    string strThemePath = "Themes\\" + themeName + "\\Theme.xaml";

    if (File.Exists(strThemePath))

        try

        {

            Application.Current.Resources = (ResourceDictionary)XamlReader.Load(new XmlTextReader(strThemePath));

        }

        catch (Exception ex)

        { throw ex; }

    else

        throw new FileNotFoundException("The Theme file was not found.\nPlease make sure the Theme is valid.");

}

Yep! I see the light! What did I do here? Simple! I use a XamlReader to load the theme.xaml file, cast it to a ResourceDictionary and then make those resources avaliable for all the application. Despite what you might think this process adds the resources in the theme.xaml file to the current app resources, then why not clear the app resources? For two reasons, first, because you might have styles specified in the app code that require the default WPF styles, second, because when you want to test a new theme that you’re creating you need to complete the theme before you can test parts of it. So, if you load the blue theme and then you have a red theme that you just started creating and it only has a template for the Button when you load the theme, the app will use the red template for the button and the blue template for the rest of the styles that aren’t found in the red theme.

This concludes the first part of how to allow full customization with a Resource Dictionary, in the next post I’ll be covering the basics of the Resource dictionary. Stay tuned!

5 Responses to “How to allow full customization with a Resource Dictionary? (Part I)”

  1. thylux Says:

    When’s the ‘juice’ comming?

  2. Bruno Silva Says:

    Maybe today 🙂

  3. xiaoyuanfxy Says:

    Hi, I’m changing a ResourceDictionary at runtime after usercontrol is loaded. Unfortunately this works only once because my ResourceDictionary.IsReadOnly = true later. Do you have any idea ?

  4. qwerty Says:

    Hi, I’m changing a ResourceDictionary at runtime after usercontrol is loaded. Unfortunately this works only once because my ResourceDictionary.IsReadOnly = true later. Do you have any idea ?


Leave a reply to Steve Arvid Cancel reply