All about ResourceDictionary in WP7
published on: 2/25/2011 | Views: N/A | Tags: Silverlight
by WindowsPhoneGeek
In this article I am going to talk about ResourceSictionaries in Silverlight for Windows Phone 7. I will explain all you need to know about them and also I will give lots of examples of how to create, use and access them.
What is ResourceSictionary?
A resource dictionary is a keyed dictionary of objects(resources) that can be used both in XAML and in code. Resource dictionaries can exist at several positions in an application structure, including as immediate (page) resources, application resources (as part of the Application object) or as XAML files that are kept separate in the application project structure.
With just a few exceptions, the items within a ResourceDictionary must each have a key defined. In XAML, you assign the key by providing a value for the x:Key attribute on the object element that is added as ResourceDictionary content. In code, the key is provided as a parameter for methods such as ResourceDictionary.Add. Resources in a Silverlight XAML ResourceDictionary must use strings for their key names.
FrameworkElement.Resources and Application.Resources are two Silverlight properties that take values of type ResourceDictionary. Generally, you define the FrameworkElement.Resources value on the root element of a XAML page (PhoneApplicationPage). Application.Resources provides application-scoped resources. The resources that are defined by Application.Resources are available no matter what page or other UI is loaded as the current RootVisual of the application.Specifying resources at the application level might be useful if you are loading different possible pages into the RootVisual, and want a way to avoid duplicating the same resources in each possible page.
Silverlight ResourceDictionary sharing behavior support the following classifications of objects for shareable usage:
-
Styles and templates.
-
Brushes and colors.
-
Animation types including storyboards.
-
Transforms.
- Certain other structures that have settable and constructible properties, such as Thickness and CornerRadius. However, these often require an initialization text usage in XAML in order to declare useful values; see XAML Usage sections in the reference topics for more information.
-
Custom types that are defined in your backing code, then instantiated in XAML as a resource. Examples of this are converters for resources, CLR objects for data sources, or IValueConverter implementations for data binding.
-
Strings and basic numeric values such as double and int. Note that object element usage in XAML for these system types requires that you map the System namespace and mscorlib assembly where the backing types for each CLR primitive are defined. The syntax for this is typically xmlns:sys="clr-namespace:System;assembly=mscorlib". For more information about XAML namespace mapping, see Silverlight XAML Namespaces, and Mapping XAML Namespaces as Prefixes.
A merged resource dictionary enables you to declare the contents of a resource dictionary by referencing an external file, and to use the externally defined resources to augment the resources found in an existing FrameworkElement.Resources property location. To declare a merged resource dictionary, you add a property element for the MergedDictionaries property to an existing ResourceDictionary location. You can use merged dictionaries for the FrameworkElement.Resources or Application.Resources;
Dictionaries are merged by adding a ResourceDictionary to the generic collection referenced by MergedDictionaries. The merged dictionary is a ResourceDictionary with no markup child elements defined (or with no elements added through code), but with a URI specified for Source. When used as a merged dictionary source, it is illegal for a XAML file that has a ResourceDictionary root to specify x:Class.
generic.xaml
generic.xaml is used when creating custom controls in Silverlight for WP7. It is a special implementation and deployment technique used for controls that generally incorporates a ResourceDictionary. For more information take a look at the Creating a WP7 Custom Control in 7 Steps article. Inside generic.xaml only, both Name / x:Name and x:Key are optional on Style elements so long as the TargetType attribute is specified (the TargetType is implicitly used as the key).
NOTE: For more information about ResourceSictionaries visit the official MSDN Documentation.
NOTE: For more information about Merged Resource Dictionaries visit the MSDN Documentation.
NOTE: Duplicate keys across the collection of merged dictionaries are not illegal.
How to cerate a ResourceDictionary file in Windows Phone 7?
By default it's not possible to create a new ResourceDictionary file using the default VisualStudio Templates.However you can create it on your own using the following workaround:
1. Create a .cs file named MyResourceDictionary.cs
2. Change the file extension to .xaml: MyResourceDictionary.xaml
3. Add the following code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
//add some code here
</ResourceDictionary>
How to use ResourceDictionaries in Windows Phone 7?
1. Using a ResourceDictionary file from the current assembly
If we have a ResourceDictionary file in the current project then we can include it into the app resources through the ResourceDictionary MergedDictionaries property. Lets say that we have a file TestStyles.xaml with the following code into it:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="TextBlockStyle1" TargetType="TextBlock">
<Setter Property="Foreground" Value="Orange"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
</ResourceDictionary>
We can add it to the resources of our application in this way:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TestStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
We can use the styles from the dictionary it in the following way:
<TextBlock Style="{StaticResource TextBlockStyle1}"/>
2. Using a ResourceDictionary file from external assembly
Lets say that we have two projects Project1 and Project2. We will add a TestStyles.xaml ResourceDictionary file into Project1 and will use it in Project2. In order to do this here are the steps:
1.Add reference to Project1 in Project2
2. Add the following code into the App.xaml Resources section of Project2:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Project1;component/TestStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
NOTE: If the build action of the ResourceDictionary file is set to Resource you can reference it in this way:
/<assembly name>;component/<resource file path>
If the build action is set to Content then you can reference it in this way:
/<resource file path>
After that we can use the style in our Project2 -> MainPage.xaml in this way:
<TextBlock Style="{StaticResource TextBlockStyle1}"/>
3. Add ResourceDictionary to the PhoneApplicationPage Resources
We can add any particular ResourceDictionary to the resources of a PhoneApplicationPage in this way:
<phone:PhoneApplicationPage.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TestStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</phone:PhoneApplicationPage.Resources>
We can use the styles from the dictionary in the following way:
<TextBlock Style="{StaticResource TextBlockStyle1}"/>
4. Add ResourceDictionary programatically
If you want to include any particular ResourceDictionary file to the resources of our app programmatically then you have to do this into the App.xaml.cs constructor immediately after InitializePhoneApplication(). Otherwise you will get an exception!
public App()
{
...
// Standard Silverlight initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
LoadDictionary();
}
private void LoadDictionary()
{
var dictionaries = Resources.MergedDictionaries;
dictionaries.Clear();
string source = String.Format("/WP7SampleProject23;component/TestStyles.xaml");
var themeStyles = new ResourceDictionary { Source = new Uri(source, UriKind.Relative) };
dictionaries.Add(themeStyles);
}
After that you can use the styles as expected:
<TextBlock Style="{StaticResource TextBlockStyle1}"/>
5. Using generic.xaml
In case you are creating a custom control then all you need to do in order to use/access generic.xaml is to add the following code in the constructor of your control:
public MyCustomControl()
{
DefaultStyleKey = typeof(MyCustomControl);
}
DefaultStyleKey gets or sets the key that references the default style for the control. To provide a default Style for a control that inherits from Control set the DefaultStyleKey property to the same type of the TargetType property. If you do not set the DefaultStyleKey, the default style for the base class is used.
That was all about using ResourceDictionaries in Silverlight for Windows Phone 7. You can get the full source code here:
I hope that the article was helpful.
You can also follow us on Twitter @winphonegeek
Comments
Can also merge Inline dictionary for easier debugging
posted by: Greg Bray on 2/28/2011 10:01:03 PM
Great article! Moving common styles to an external resource file is a great way to clean up your app.xaml file, but be warned that it is much harder to debug styles that are not part of the main app.xaml. If you have a key typed incorrectly or if there is a syntax error you might not find out about it until runtime.
A great way to work around this is to start by writing your style/resource objects using an "inline" ResourceDictionary and then move them off to a separate file when you know they are working correctly. Something like:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TestStyles.xaml"/>
<ResourceDictionary Source="TestStyles2.xaml"/>
<ResourceDictionary>
<local:LocalizedStrings xmlns:local="clr-namespace:WP7_App.Localization" x:Key="myLocalizedStrings" />
<local:URItoImageBrushConverter xmlns:local="clr-namespace:WP7_App" x:Key="myURItoImageBrushConverter" />
<local:VisibilityConverter xmlns:local="clr-namespace:WP7_App" x:Key="BooleanVisibilityConverter" />
<Style x:Key="TextBlockStyle1" TargetType="TextBlock">
<Setter Property="Foreground" Value="Orange"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Loading resource dictionary in code not working for me
posted by: Darlene M on 7/30/2011 3:00:29 PM
In Step 4. above, you mention
"If you want to include any particular ResourceDictionary file to the resources of our app programmatically then you have to do this into the App.xaml.cs constructor immediately after InitializePhoneApplication(). Otherwise you will get an exception!"
Why does it need to go right under? I am getting exceptions with loading the dictionary in the code, but even though I have it exactly as you do above, I am still getting exceptions.
RE:@Loading resource dictionary in code not working for me
posted by: winphonegeek on 8/19/2011 7:00:10 PM
Can you give us some more info about the exception?
btw, things are a little bit different in Windows Phone 7.1 Mango. So everything should be working now. Here is an updated post: How to port your WP7 custom application Theme to Windows Phone Mango
Our Top Articles & Free books
- Our FREE e-book: "Windows Phone Toolkit In Depth" 2nd edition
- 400+ Windows Phone Development articles in our Article Index
- 21 WP7 Toolkit in Depth articles covering all controls
- 12 WP7 Coding4Fun Toolkit in Depth articles covering all controls
- Performance Tips when creating WP7 apps
- Creating a WP7 Custom Control in 7 Steps
- WP7 working with VisualStates: How to make a ToggleSwitch from CheckBox
- What makes a WP7 App successful
- Creating theme friendly UI in WP7 using OpacityMask
- Implementing Windows Phone 7 DataTemplateSelector and CustomDataTemplateSelector
- All about Splash Screens in WP7 – Creating animated Splash Screen
- Getting Started with Unit Testing in Silverlight for WP7
- WP7 WatermarkedTextBox custom control
Our Top Tips & Samples
- All about WP7 Isolated Storage series
- WP7 Dynamically Generating DataTemplate in code
- 5 tips for a successful WP7 Marketplace submission
- WP7: Navigating to a page in different assembly
- WP7 ContextMenu: answers to popular questions
- WP7 ListBox: answers to popular questions
- WP7 working with Images: Content vs Resource build action
- WP7 Element Binding samples
- WP7 working with XML: reading, filtering and databinding
- Drawing in WP7: #2 Drawing shapes with finger
- WP7 TextBox Light theme problems - the solution
- Changing the WP7 Panorama Background Image dynamically with Animation
