Like pancakes...

the random ramblings begin...
in

May 2009 - Posts

Load XAML Resource Dictionaries at Runtime

This topic has been covered by many people, but since I was recently looking at it myself, I thought I’d add it here.

My idea is to load resources at runtime to enable hot swapping of skins without having to recompile or restart the application. The basic idea is that you define a loose XAML file that contains all the resources you’d like to be swappable, then you load those resources at runtime. You can then change the XAML file at anytime and reload those resources.

In this example my window contains a simple uniform grid that uses dynamic resources to populate the fill color of rectangles.

<UniformGrid Rows="2" Columns="2">
    <Rectangle Fill="{DynamicResource brush1}"/>
    <Rectangle Fill="{DynamicResource brush2}"/>
    <Rectangle Fill="{DynamicResource brush3}"/>
    <Rectangle Fill="{DynamicResource brush4}"/>
</UniformGrid>
Note that you must use DYNAMIC resources for this to work. Otherwise the brush will be pulled from the App.xaml Resource block and will not update at runtime.

OK, so, now let’s add some resource files. Outside of the project I’ve created two resource dictionaries and named them “skin.xaml” and “skin_other.xaml.” These both hold simple SolidColorBrush definitions with different colors and are placed in the bin folder. They look like this:

skin:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="brush1" Color="Black"/>
    <SolidColorBrush x:Key="brush2" Color="Gray"/>
    <SolidColorBrush x:Key="brush3" Color="Brown"/>
    <SolidColorBrush x:Key="brush4" Color="LightGray"/>
</ResourceDictionary>

skin_other:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="brush1" Color="Blue"/>
    <SolidColorBrush x:Key="brush2" Color="Red"/>
    <SolidColorBrush x:Key="brush3" Color="Green"/>
    <SolidColorBrush x:Key="brush4" Color="Yellow"/>
</ResourceDictionary>

OK, so we’ve got the window ready to display our colors, and we’ve got our colors defined…all that’s left is to actually load and swap them. Inside App.xaml.cs I can load a resource dictionary with these two lines of code:

ResourceDictionary rd = (ResourceDictionary)XamlReader.Load(System.Xml.XmlReader.Create("skin.xaml"));
this.Resources.MergedDictionaries.Add(rd);

And that’s all it takes. Simple. Here though, to continue with my “hot swap” example, I’ve set up a timer which will switch between the two resource dictionaries every two seconds.

public partial class App : Application
{
    DispatcherTimer timer = new DispatcherTimer();

    public App()
    {
        timer.Interval = new TimeSpan(0, 0, 2);
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    private bool flip = true;
    void timer_Tick(object sender, EventArgs e)
    {
        ResourceDictionary rd;
        if (flip)
        {
            rd = (ResourceDictionary)XamlReader.Load(System.Xml.XmlReader.Create("skin.xaml"));
        }
        else
        {
            rd = (ResourceDictionary)XamlReader.Load(System.Xml.XmlReader.Create("skin_other.xaml"));
        }

        this.Resources.MergedDictionaries.Add(rd);
        flip = !flip;
    }
}

And that is how you load resource dictionaries at runtime. Hope you enjoyed it.

Oh, one final note, I’ve added my newly loaded resource dictionary to the MergedDictionaries so that there is no impact on any other resources that might have been included in the application.