WPF Resources

Resources in WPF terms, are simply mechanisms for storing data, whether it be strings, colours, brushes, styles etc.

We can store such resources locally, within the scope of a Window or control or we can store the resources globally within the Application resources.

Resources are stored as key value pairs within a Resources section or ResourceDictionary. We therefore need to define a x:Key for each item in the resources, for example

<Window.Resources>
   <system:Int32 x:Key="ButtonWidth">100</system:Int32>
</Window.Resources>

In the above XAML we’re storing an Int32 type in the resource of a Window class. The key is “ButtonWidth” and the value is “100”.

Now let’s look at some example of using the resources.

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <FontWeight x:Key="Weight">Black</FontWeight>
    </Window.Resources>    
    <Grid>
        <Button Content="Hello World" FontWeight="{StaticResource Weight}" />
    </Grid>
</Window>

In the XAML above we are storing the resources within the scope of the Window. This means everything within the Window class will now have access to these resources but they’re not available outside of this Window.

We’ve created a FontWeight type resource with the key “Weight”. In the Button we use the resource to assign the value from the key “Weight” to the FontWeight of the Button. simply think of the key as a variable name.

Note: I’ll discuss the StaticResource at the end of this post

We can add resources to a top level UserControl (for example) just as we’ve done in the Window example, but we can also add resources to controls within a control or Window, for example, let’s take the Button from the above example but move the resource into the Button.Resources

<Button Content="Hello World">
   <Button.Resources>
      <FontWeight x:Key="Weight">Black</FontWeight>
   </Button.Resources>
   <Button.FontWeight>
      <Binding Source="{StaticResource Weight}"/> 
   </Button.FontWeight>
</Button>

Notice in the code above, we’ve used the Button.FontWeight element instead the FontWeight attribute of the Button (as per the original code). This is simply because when we add the resources in this way, these are now within the scope of the Button and unfortunately this means we cannot apply to the Button attributes themselves.

Application resources are defined in much the same way as for a Window resources but are available to all Windows/controls – in other words have global scope. We might declare our resource as follows

<Application x:Class="Test.App"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   StartupUri="MainWindow.xaml">
   <Application.Resources>
      <FontWeight x:Key="Weight">Black</FontWeight>
   </Application.Resources>
</Application>

Finally we can also create XAML files which are of type ResourceDictionary

<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
   <FontWeight x:Key="Weight">Black</FontWeight>
</ResourceDictionary>

Now to use this ResourceDictionary from our Window (or control) we need to writing the following

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MyResources.xaml"></ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources> 

This will merge the MyResources.xaml into the Windows ResourceDictionary and thus make the FontWeight resource available to the Window as if we’d declared it within the Window Resources. However by using the ResourceDictionary, not only can we create tidier code, removing possibly lots of resources from our views but also create libraries of resources that can be easily reused.

Resource Markup Extension

In the code above, we used the StaticResource markup extension. This is not the only option for binding to resources. We could also use the DynamicResource markup extension.

The use of StaticResource means that resource is resolved once at the point the XAML is loaded. Whereas DynamicResource allows us to in essence, late bind, to the resource. This means we can write XAML which might have a DynamicResource binding to a resource but the resource doesn’t need to exist until runtime. This option also allows the binding to update automatically if the resource changes. Hence if you want to bind to a resource which might change, then you can use a DynamicResource – this is obviously very useful when we’re dealing with the concept of themes.

And finally

In some cases we might want to use the resource in code. If we’re embedding the string for the key within the XAML, this means we’ll have to duplicate the string in code – duplication is not good. So instead we might prefer to store the string in source code to begin with and reference this in our XAML.

So let’s create a C# file named it whatever you like, I’m going to call mine’s Constants.cs

Now let’s just create the following static class

public static class Fonts
{
   public const string Weight = "Weight";
}

We can obviously use this “Weight” in our code, but in XAML we’re going to need to do the following change.

<!-- Original -->
<FontWeight x:Key="Weight">Black</FontWeight>

<!-- Becomes -->
<FontWeight x:Key="{x:Static local:Fonts.Weight}">Black</FontWeight>