BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Resources

The one hundred and forty-seventh part of the Windows Presentation Foundation Fundamentals tutorial looks at resources. These allow the reuse of shared items, such as styles, templates, type converters and many other objects.

Referencing the Resource

So far, the resource has not been used by the Ellipses. You apply a resource to a property with a markup syntax that is similar to that of data binding. There are two ways to link the resource to a property. Initially, we will use static binding with the StaticBinding markup extension. This is set as the target property's value, along with the key of the resource. For example:

{StaticResource BlueSky}

Let's apply the BlueSky resource to the four shapes. Replace all four Ellipse elements with the following code:

<Ellipse Fill="{StaticResource BlueSky}" />
<Ellipse Fill="{StaticResource BlueSky}" />
<Ellipse Fill="{StaticResource BlueSky}" />
<Ellipse Fill="{StaticResource BlueSky}" />

You can see that this makes the code much less repetitive and more readable. Also, if you wish to change the appearance of all of the ellipses, you can do so by modifying the brush in the resource.

Resource Scopes

As mentioned earlier, a resource can be defined against any framework element. This allows you to create multiple dictionaries at different places in the logical tree, depending upon which controls you wish to be able to access them. Generally though, you will declare local resources at the root of a XAML document.

If you want to re-use resources in many windows, it would not be sensible to create multiple copies of a resource dictionary. It would be much more useful to create a single dictionary that can be shared across an entire application. WPF allows you to create such a dictionary using the App.xaml file.

Visual Studio creates the App.xaml file automatically in new WPF application solutions. The file includes a XAML document and a linked code file, both of which are shared across the entire program. If you create your resource dictionary in the XAML file, you can centralise resources, allowing them to be changed once to affect the entire solution.

To demonstrate, remove the Window.Resources element from the XAML of the main window. Visual Studio will highlight the StaticResource markup to show that there is a problem because the named resource cannot be found. If you run the program, it will fail.

Next, double-click the App.xaml file in the solution explorer. The XAML file will be opened. It should contain code similar to that shown below:

<Application x:Class="ResourcesDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Note the Application.Resources section. This is where you can define application resources that will be available for the whole program. Add the linear gradient brush we used earlier to the file. The complete App.xaml should appear as follows:

<Application x:Class="ResourcesDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <LinearGradientBrush x:Key="BlueSky" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="Cyan" Offset="0.2"/>
                <GradientStop Color="LightBlue" Offset="0.4"/>
                <GradientStop Color="White" Offset="0.5"/>
                <GradientStop Color="White" Offset="0.6"/>
                <GradientStop Color="DarkGray" Offset="0.6"/>
                <GradientStop Color="Black" Offset="0.8"/>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Application.Resources>
</Application>

If you switch back to the main window you'll find that the resource references are no longer highlighted. If you run the program, you'll see that it now runs correctly with the linear gradient applied to each ellipse.

Static vs Dynamic Resource References

In the examples so far, we've linked a property to a resource using the StaticResource markup. This specifies that you wish to use the resource with a static reference. You can also use the DynamicResource keyword to declare a dynamic reference. If you change the code for each of the ellipses to the following, you will see that the resultant window appears identical.

<Ellipse Fill="{DynamicResource BlueSky}" />

Although the results are the same in this instance, there are differences between the two markup options. In some situations, you must choose one option or the other. In other cases, both versions will produce the same results but one might perform marginally better than the other.

Static Resource References

When you use the StaticResource markup to link to a resource, the object is retrieved once, at the start of its life, and it remains fixed. If the resource is changed through code, those changes are not reflected in the items that reference it. In our example, changing the gradient stop colours of the resource would not update the ellipses.

Static resource references are used when the resource is to be packaged into an executable or dynamic link library. They can provide slightly better performance than dynamic resources.

To find a static resource, WPF first looks in the control that includes the StaticResource markup. If the desired object does not exist here, the logical tree is traversed upwards until the item is located. If it still cannot be found, the application resources are checked.

A referenced static resource that exists in the local XAML document must be defined before it is used. If the resource appears below the control using it, it will not be found and the program will fail to run correctly.

Dynamic Resource References

Dynamic resources are resolved at run time. This means that they are particularly useful when they provide access to values that might change, either before the software is started or during execution. Changing the resource also updates the property values that are bound to it. This is useful for resources that are not created until the software is started, for user settings and preferences, which might be updated, and for system settings, such as standard operating system fonts and colours.

WPF locates dynamic resources in a slightly different manner to static ones. As before, the resources attached to the control that references a resource are checked first. If the desired resource is not found, the logical tree is traversed in an upwards direction. Next the application resources are examined. Once all of these options have been exhausted, dynamic references check system resources. In addition, forward references can be resolved, allowing items defined in XAML after the reference to be used.

Although dynamic resources provide benefits over static references, you should generally prefer the static option. Dynamic resources can provide lower performance than static ones. Static references are also acceptable in more scenarios. Dynamic resources can only be used with dependency properties, style setters or properties defined on a class that inherits from Freezable.

29 March 2015