Silverlight
Resource Dictionaries

[Note: This topic is pre-release documentation and is subject to change in future releases. Blank topics are included as placeholders.]

A resource dictionary is a concept supported by the ResourceDictionary class. A resource dictionary is a keyed dictionary of objects that can be used both in XAML and in code. XAML is the most common usage, particularly for initially defining objects in a resource dictionary. 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 and unloaded in the application structure, for later run-time use. Resource dictionaries commonly support two major Silverlight scenarios: defining templates for controls, and defining storyboards for animated properties.

This topic contains the following sections.

ResourceDictionary for JavaScript API

ResourceDictionary existed as an object in Silverlight 1.0 and can also be accessed by the JavaScript API for limited scenarios. This topic does not cover those scenarios. See ResourceDictionary.

Objects For ResourceDictionary Usage

Not all classes/objects are suitable for ResourceDictionary usage in Silverlight. In order for an object to be defined in and accessed from a ResourceDictionary, the object must be able to be shared. This is a requirement because ultimately when the object tree for an application is constructed and used at run time, objects cannot exist at multiple locations in the tree without either a sharing mechanism or an indirection mechanism. In general, a UIElement type is not shareable, unless it is generated from a style or template.

Silverlight ResourceDictionary usages support the following:

  • Styles and templates

  • Brushes and colors

  • Animation types including storyboards

  • Transforms

  • Custom types such as converters for resources

  • 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, for example xmlns:sys="clr-namespace:System;assembly=mscorlib")

Keys and Resources

The items within a ResourceDictionary must each have a key defined. A ResourceDictionary is a dictionary, not a collection. In XAML, you assign a key by providing a value for the x:Key attribute on the object element that is added as ResourceDictionary content. In the Silverlight implementation, a ResourceDictionary can have an x:Name instead of or in addition to an x:Key. If x:Key is not specified, the x:Name is used as the key.

NoteNote:

Some tools or development environments may give warnings about XAML that contains a ResourceDictionary that has items with x:Name but no x:Key. However, the x:Name / x:Key equivalence will be valid for run-time XAML parsing.

If you intend to use keyed resources from XAML markup, you generally map the XAML namespace to an XML namespace, through an xmlns declaration. This is usually necessary because x:Name and x:Key are defined by the XAML namespace.

NoteNote:

The Silverlight documentation assumes the typical mapping prefix of x: for the XAML namespace, therefore references to "Key" in the documentation are typically in the form x:Key, with the assumed x prefix appended. Also, it is typical to map both the default Silverlight namespace and the XAML namespace at the root element level.

Resources in a Silverlight ResourceDictionary generally use strings for their key names. See XamlName Grammar for string value restrictions on key names. The value used for key names in Silverlight must conform to this grammar.

If you include an item that does not have a usable key in a resource dictionary, a parser exception occurs. If you duplicate a key, a parser exception occurs. In general, if there are problems with keys, with object elements that cannot be created, or with resource lookup, the problems are not detected during markup compilation, and are only reported as exceptions when Silverlight attempts to load the XAML at run-time.

Immediate and Application Resources

There are two properties that take values of type ResourceDictionary: FrameworkElement..::.Resources, and Application..::.Resources. FrameworkElement..::.Resources provides what might be termed immediate resources. In XAML, you can reference the keyed resources from FrameworkElement..::.Resources from any element that is connected to the same object tree as the resources exist within. Generally, you define the FrameworkElement..::.Resources value on the root element of a XAML page, and generally for a user application the root element for UI pages is UserControl. Therefore the common usage is to define all immediate resources that might be used by a page as elements within UserControl.Resources.

Application..::.Resources provides what might be termed application-scoped resources. The resources that are defined by Application..::.Resources are available no matter what page is loaded as the current RootVisual of the application. This might be important if you are loading different possible pages into the RootVisual, and want a way to avoid duplicating the same resources in each possible page. Also, if you are writing values into a resource dictionary at run-time, this provides a location where those resources can persist for the application lifetime.

NoteNote:

Do not confuse the concepts related to ResourceDictionary with the Resources build action, .resx files, and other "resources" that are discussed in the context of how you might structure the project that produces an application in MSBUILD or a development environment such as Visual Studio. Although the notion of resources for build actions and application structure can overlap with ResourceDictionary usages, the ResourceDictionary can generally be thought of as providing a self-contained resources system that incorporates XAML as its primary definition format.

Referencing Resources from XAML

In XAML, you reference a resource by using the StaticResource markup extension. To use the markup extension, you always reference the property you are setting through an attribute usage. For instance, to set the value of the Background property of a Button to be a resource, you would write something similar to the following XAML:

<!--item in a ResourceDictionary-->
<LinearGradientBrush x:Key="fadeBrush">
  <GradientStop Color="Red" Offset="0"/>
  <GradientStop Color="Gray" Offset="1"/>
</LinearGradientBrush>
<!--XAML that defines the actual UI-->
<Button Background="{StaticResource fadeBrush}" .../>

You use attribute syntax for a resource reference even if the property you are setting normally takes an object, and thus would require a property element usage in XAML if you were defining the setting object inline rather than as a resource. For instance, the following is an equivalent property element usage, if the LinearGradientBrush is defined inline:

<Button>
  <Button.Background>
    <LinearGradientBrush>
      <GradientStop Color="Red" Offset="0"/>
      <GradientStop Color="Gray" Offset="1"/>
    </LinearGradientBrush>
  </Button.Background>
</Button>
NoteNote:

You cannot explicitly use a property element usage surrounding StaticResource as object element content. In Silverlight 2 the StaticResource markup extension only supports usage as an attribute value (not as an object element).

Lookup Behavior for StaticResource

The lookup behavior for a StaticResource is that the markup compile pass for XAML will first check whether the object where the actual usage is applied is even capable of holding a FrameworkElement..::.Resources value. If so, that ResourceDictionary is checked for an item of that key. This level of lookup is seldom relevant, because you usually do not define then reference a resource on the same object. More relevant is what happens next: the markup compile pass checks the next object tree parent for FrameworkElement..::.Resources and if the property exists there, checks for the key. This continues until the root element of the XAML is reached. Both to take advantage of this behavior and also as a matter of markup style, it is typical to define all the immediate resources at the root level of a page.

If the requested resource is not found in the immediate resources, then the next lookup step is to check Application..::.Resources.

If after this sequence the requested key is still not found, a parser exception occurs.

Based on this lookup behavior, it is possible to deliberately define multiple resources that have the same string value as the key, so long as each such resource is defined at a different element level where there is a FrameworkElement..::.Resources property to maintain key uniqueness. Only the first such object retrieved is used for the StaticResource. You could use this behavior to retrieve the same StaticResource key at various levels of the object tree yet obtain different results.

Forward References Within a ResourceDictionary

Static resource references from within a resource dictionary must reference a resource that has already been defined lexically before the resource reference. Forward references cannot be resolved by a static resource reference. For this reason, if you use static resource references, you must design your resource dictionary structure such that resources intended for further by-resource use are defined at or near the beginning of each respective resource dictionary.

References Between Application and Immediate Resources

Resources defined for the application cannot make references to immediate resources. This is equivalent to attempting a forward reference, because the application resources are actually processed first. However, any immediate resource can make a reference to an application resource, and this can be a useful technique for avoiding forward references.

Resource Dictionaries and XamlReader.Load

You can use a ResourceDictionary as either the root or a part of the XAML input for XamlReader..::.Load. You can also include StaticResource references in that XAML, so long as all such references are entirely self-contained in the XAML. XamlReader..::.Load parses the XAML in a context that is not aware of any other ResourceDictionary objects, not even Application..::.Resources.

StaticResource in Templates

Any StaticResource in a template is evaluated in the context of where the template is defined rather than where the template is applied. Usually this means that a StaticResource reference in a template must come from other items defined lexically previous from it in the same ResourceDictionary or from Application..::.Resources.

Referencing Resources from Code

In code, you can reference a resource by using the indexer (Item). In this indexer case the indexer uses the key, not an integer index. Usually a prerequisite is to retrieve a specific ResourceDictionary, either an immediate ResourceDictionary somewhere in the object tree by getting FrameworkElement..::.Resources, or the application ResourceDictionary by calling Application..::.Current, then Application..::.Resources.

NoteNote:

Silverlight does not implement the FindResource method that exists in the WPF framework.

Run-Time Usages

You can declare a resource dictionary as a discrete XAML file, and load it at run time with Load and load-from-package APIs from application services. In this case, ResourceDictionary is declared as an object element, serving as the root element of the XAML. You must map the appropriate XML namespaces (default for Silverlight and x: for XAML) onto the ResourceDictionary element if you plan to use it as the root element. Then you can add object elements for items that define the resources, each with a key. However, if this ResourceDictionary is intended to provide resources called by StaticResource in XAML, you must attach the ResourceDictionary to an existing Resources property so that it participates in the lookup sequence (for instance you could use Startup to set Application..::.Resources).

Another possible run-time usage is to add items to a ResourceDictionary by calling Add. You could add to either immediate resources or application resources. At run-time, there is little that distinguishes a ResourceDictionary versus a dictionary you could have created yourself, except that a ResourceDictionary is often populated from the initial XAML, and ResourceDictionary is convenient because you can obtain a ResourceDictionary from existing FrameworkElement..::.Resources / Application..::.Resources properties.

The run-time Add call requires a key, which satisfies the requirement that each item in a ResourceDictionary has a key. For anything that is added to a ResourceDictionary at run-time you will be unable to provide a value for x:Name that is accessible to the XAML namescope of the main object tree, because x:Name and the equivalent Name are both only settable from XAML. Although you could call XamlReader..::.Load first to load XAML that included internal x:Name / Name attributes, and then add the created object tree as a resource, this does not solve the names-in-main-namescope problem because Load always creates a discrete XAML namescope. The restriction on setting Name at runtime is generally not a problem, but could become an issue if you are trying to use storyboards to animate properties on objects added to resources at run-time, and need a TargetName. For these cases you can still use a true PropertyPath in order to indirectly target the property by starting the property path from some object in the tree that does have an available name in the main XAML namescope.

Reusing Resources

In some cases you can assign a value that is defined in a resource to more than one object.

  • Templates and styles defined in a ResourceDictionary can always be reused, because the mechanisms that apply templates or set styled properties are designed for that purpose.

  • Value types, such as strings, can be used more than once. Any value type that is reused is just copied. (Including strings and other System defined value types in object element XAML usage such that they can be keyed requires mapping an XML namespace with prefix for System and mscorlib; see XAML and Mapping Custom XML Namespace Values).

  • The resource system also supports built-in sharing of certain objects if they are used more than once. These objects are:

Objects that go in a visual tree, such as any UIElement, generally cannot be retrieved from a resource dictionary more than once, and attempting to do so will generate a parser exception. Attempting to reuse object definitions is a scenario for templates, not a resource dictionary per se. Another possible approach for object definition reuse is to use XAML input for XamlReader..::.Load but call the method multiple times on the same XAML input to return more than one object.

generic.xaml

generic.xaml is a special implementation technique used for controls that generally incorporates a ResourceDictionary. Inside generic.xaml only, both Name / x:Name and x:Key are optional on Style elements if the TargetType attribute is specified. Another aspect that is unique to generic.xaml is that the {x:Type} markup extension is supported when setting TargetType for styles and template resources. This is to support compatibility and migration. Outside of generic.xaml, the SilverlightXAML parser uses implicit conversion for any property of type Type, and explicit use of {x:Type} is not supported and generates a parser error. For more information on generic.xaml, see Creating a Control That Has a Customizable Appearance.

ResourceDictionary Implementation Differences from WPF

  • As noted in the "Keys and Resources" section, a Silverlight ResourceDictionary can have an x:Name instead of or in addition to an x:Key. WPF always requires x:Key except for certain explicit key cases related to styles and templates.

  • Silverlight does not support FindResource (not strictly a ResourceDictionary issue, but relevant to the overall usage).

  • Silverlight does not support {DynamicResource}. If you are migrating XAML from WPF, you can convert these to {StaticResource} and define them in a ResourceDictionary, or you must otherwise replace the references. Again, not strictly a ResourceDictionary issue.

  • In WPF, the base type for templates (FrameworkTemplate) also had a Resources property. The Silverlight version of FrameworkTemplate does not have a Resources property.

  • Silverlight XAML does not support x:Shared or x:Static.

  • Silverlight has a smaller range of shareable types than WPF. Some types that are shareable in WPF, such as Geometry, are not shareable in Silverlight.

See Also

Reference

Concepts

Page view tracker