Ask Learn
Preview
Please sign in to use this experience.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article has a corresponding video that can be viewed here.
Resource Dictionaries are a powerful feature in WPF and Silverlight that enable developers to organize and consume reusable resources.
After completing this walk through you'll understand how to create and merge resource dictionaries in WPF and Silverlight; how to add, consume and modify resources in the dictionary using the tools provided by the WPF and Silverlight Designer in Visual Studio 2010.
Before diving into resource dictionaries let's first understand what the term "resource" means when used in the context of a resource dictionary or in a resources section of an object in XAML.
A resource is an object declared in XAML. In the below XAML we see examples of typical resources; my: is an alias for the System namespace in mscorlib.
<UserControl.Resources>
<LinearGradientBrush x:Key="formBackground" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="#460000FF" Offset="1" />
</LinearGradientBrush>
<my:String x:Key="applicationTitle">Resource Dictionary Demo</my:String>
<my:Double x:Key="applicationTitleFontSize">18</my:Double>
<SolidColorBrush x:Key="applicationTitleForeground">Yellow</SolidColorBrush>
</UserControl.Resources>
One reason to use resources in your applications is to promote object reuse across your application. Object reuse provides consistency across the application. Object reuse also makes it very easy to change the application; since you only need to change the resources and all consumers will pick up the change.
The below XAML consumes the above resources.
<Grid x:Name="LayoutRoot" Background="{StaticResource formBackground}">
<TextBlock
Text="{StaticResource applicationTitle}"
Foreground="{StaticResource applicationTitleForeground}"
FontSize="{StaticResource applicationTitleFontSize}"
VerticalAlignment="Top"/>
</Grid>
Resources are located in resource dictionaries.
What I have referred to as a resources section is actually the Resources property (WPF Silverlight) which is of type ResourceDictionary. When you add resources to the Resources property, you are actually adding them to a ResourceDictionary exposed by the object.
The Resources property is defined on FrameworkElement and is inherited from any object that has FrameworkElement in its inheritance hierarchy. This means that resources can be located on Windows, UserControls, Grids, Buttons, TextBoxes, ListBoxes, etc.
In addition to an objects Resources property, resources can also be located in a ResourceDictionary XAML file.
Create a new WPF or Silverlight project and add the following XAML.
<Grid x:Name="LayoutRoot">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="#460000FF" Offset="1" />
</LinearGradientBrush>
</Grid.Background>
<TextBlock
Text="Resource Dictionary Demo"
Foreground="Yellow"
FontSize="18"
VerticalAlignment="Top"/>
</Grid>
Select the Grid on the design surface
Using the Properties Window:
Step One:
Step Two:
Step Three:
We will now use the "Extract Value to Resource…" feature of the Designer. To exact a property value to a resource, click on the Property Marker, this will open the below Context Menu. Now select, "Extract Value to Resource…"
When the Create Resource dialog opens, change the Key to "formBackground," leave the Destination value to whatever it defaulted to and click OK.
Notice that I have chosen to name the resource by its role, as opposed to what it looks like. Adopting this Key naming convention allows a resource to be changed without causing a conflict with the Key name. For example, if the Key name was BlueGradient and I assigned it to each forms Background property, then later wanted to change it to a green gradient, the name would still be BlueGradient but the color was now green. By naming the Key formBackground, I've not associated any color or type of brush with the name.
In the below image we can see what the Designer tool did for us.
To help us quickly locate the TextBlock properties that have been set, we will now use a very cool feature of the Designer's Properties Window, "Sort by property source."
Select the TextBlock on the design surface
Using the Properties Window, click the "Sort by property source" Button (top red arrow)
Using the Extract to Resource feature, extract the properties indicated by the red arrows
After extracting the above properties to resources, your XAML will look like the below image.
The required root Grid and application title TextBlock properties are now set for reuse.
Notice the yellow highlighted line of XAML. This alias was added by the Designer tool. When the Designer tool adds an alias, it names the first one, "my" the next alias, "my1", etc. For very small forms with a single alias this may be acceptable. However for most projects you'll want to use meaningful names for your aliases.
You have several options open to you to change these. First, if you define the alias in the XAML file before extracting to a resource, the Designer tool will reuse the alias when referencing the same namespace and assembly. You could also edit the XAML after the Designer tool creates it. After you have worked with WPF or Silverlight for a short time, you'll get an understanding of the aliases you use and can just add them to your new XAML files before you start adding other content to the XAML file.
The below image is the anatomy of a simple WPF or Silverlight application that is composed of hierarchy of objects nested within each other.
Note |
Silverlight does not have system scoped resources like WPF does. |
When we say resources are scoped, we mean that resources can be defined at various levels of the application hierarchy. Resources defined at a certain scope are available to all elements in or below that scope.
For example, we previously extracted property values to the UserControl scope and the child Grid and TextBlock could access those resources.
Now, what if we wanted to consume those same resources we extracted earlier in another UserControl; how could we accomplish this?
To make the resources available, to other UserControls or Windows in the application, we need to move the resources to the Application scope.
When moving resources to Application scope, you have several options available to you:
For purposes of demonstration, I've cut the UserControl Resources and pasted them into the Application Resources section. Noticed I also cut and pasted the alias "my:" too.
You can also remove the UserControl.Resource from the UserControl's XAML as I have done the Demo.xaml image below.
You'll need to rebuild the application to remove the squiggles from your UserControl's XAML. The UserControl looks exactly as it did, but is now resolving its resources from the Application scope instead of the UserControl scope. We have just enabled reuse of these resources throughout the application. You can also see how Demo.xaml is smaller in size and looks cleaner now that we have moved the resources out of the local XAML file.
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ResourceDictionaryDemo.App"
xmlns:my="clr-namespace:System;assembly=mscorlib">
<Application.Resources>
<LinearGradientBrush x:Key="formBackground" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="#460000FF" Offset="1" />
</LinearGradientBrush>
<my:String x:Key="applicationTitle">Resource Dictionary Demo</my:String>
<my:Double x:Key="applicationTitleFontSize">18</my:Double>
<SolidColorBrush x:Key="applicationTitleForeground">Yellow</SolidColorBrush>
</Application.Resources>
</Application>
<UserControl
x:Class="ResourceDictionaryDemo.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:my="clr-namespace:System;assembly=mscorlib">
<Grid x:Name="LayoutRoot" Background="{StaticResource formBackground}">
<TextBlock
Text="{StaticResource applicationTitle}"
Foreground="{StaticResource applicationTitleForeground}"
FontSize="{StaticResource applicationTitleFontSize}"
VerticalAlignment="Top"/>
</Grid>
</UserControl>
If your application only requires a few resources, locating them in the Application.xaml or App.xaml would be fine.
However, in most applications the number of resources grows quickly and must be managed early in the application lifecycle.
Resource dictionaries are used to group related resources, then those resource dictionaries are then merged at the Application or other required scope.
What we will do now is:
Open App.xaml
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="UsingResourceDictionaries.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/FormDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Open MainPage.xaml
Select the root Grid
Add a TextBlock to the Grid
Select the root Grid
Using the Properties Window:
-
Using the Create Resource dialog:
- Change the Key name to formBackground
-
From the Destination Combobox, select FormDictionary.xaml
- Notice how the ComboBox items are nested at each scope
- Click OK to close the dialog
Tip |
In the next step we will be extracting Double and String values to a resource. The Designer tool will add the "my" alias for the System namespace in mscorlib if an alias has not been added. To make your applications more readable and easier to maintain over time, you can proactively add meaningful aliases before they needed by the Designer as I have done in the yellow highlighted XAML below. |
Switch back to MainPage.xaml
Select the TextBlock
Using the Properties Window, extract the below three properties using the names indicated
Your FormDictionary.xaml file should now look like the below image
Add a new Silverlight UserControl to the project and name it, Consumer.xaml
Select the root Grid
Using the Properties Window:
When the Apply Resource Popup opens, select the formBackground resource
Notice:
Brush resources provide a preview
The selected Key is displayed at the bottom
You can search for resources by entering search text in the Search Box
Only resources with the matching type of the property that are in scope are displayed
The Silverlight Apply Resource Popup does not list system values; this is only done in WPF.
Add a TextBlock to the Grid
Using the Properties Window, set the VerticalAlignment property to Top
Using the Properties Window, set the appropriate resource for the following properties
The TextBlock's properties should not be set like the below image
Take notice of how easy it was to have both application title TextBlock's consume the resources
The next logical step from here is to learn how to combine individual resources values into a Style and then apply a single Style to a control.
This MSDN topic, WPF Styling and Templating provides a good starting point for understanding Styles.
MSDN topic WPF Resources Overview
MSDN topic Silverlight Resource Dictionaries
Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:
Thank you for your feedback and have a great day,
Karl Shifflett
Expression Team
Anonymous
June 07, 2010
Hi,
Thank you for article.
Do you have some advice (recommendation) about using resource dictionary in a complex solution ex: Silverlight Business Application + one or more WCF RIA Service Class Library.
Right now, I am not be able to see - at design tine - resources (added in App.xaml : <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> ...) in Silverlight project of WCF RIA Class Library.
Thank you
Radu Lodina
Anonymous
June 08, 2010
The comment has been removed
Anonymous
June 09, 2010
The comment has been removed
Anonymous
June 09, 2010
Radu,
I'm sorry, but I don't understand what problem you are having. I can see and apply resources merged in App.xaml, from any project within my solution using the Designer's Apply Resource dialog.
Do you have the Visual Studio 2010 RTM?
Do you have the lastest Silverlight 4 Tools for Visul Studio installed? New version on 5/13/2010. www.microsoft.com/.../details.aspx
Do you have your resource dictionaries merged in App.xaml? In order for the Designer to "see" your resources, they MUST be merged in App.xaml or merged in the Page or UserControl that is consuming them.
Please let me know so I can try and help you, thank you,
Karl Shifflett
Anonymous
June 23, 2010
This is the best post I ever seen about how to manage resources in WPF, and more than anything, it works like a charm!
Thanks a lot
Anonymous
June 23, 2010
Thank you for you kind remarks on Visual Studio and this post.
Have a great day,
Karl
Anonymous
July 12, 2010
Hi Karl,
Great post. Going through the steps I have a better feeling for how the resource dictionaries work. I'm looking at the 3 new Themes recently released that when opened in Blend as a project can be used to create a custom Theme. I like the organization and though its a bit overwhelming at first.. Forgive me for asking a possibly stupid question here, but what is the process to get from creating a new theme based on one of these 3 to using it in an application? I'm confused about which files to add to the application I want to apply the theme to and how to implicitly apply it to a large application.
Might you have a suggestion to complete that process? I'm having a difficult time finding this information.
Regards,
Bob
Anonymous
July 12, 2010
Bob,
Thank you for your kind words.
Want to be sure I understand your requirements.
You have an existing application, and you would like to be able to use one of the new themes, is that correct? You are looking for some guidance on how to plug the new theme into your application, correct?
Cheers,
Karl
Anonymous
September 15, 2011
Great article. I'm looking forward to building my first WPF app and this article has helped me understand more about using resources. Thanks.
Please sign in to use this experience.
Sign in