WPF Resources Introduction Part 2


This entry is part 2 of 4 in the series WPF Resources

Code Behind

Let’s illustrate how to use C# code behind to store and retrieve a SolidColorBrush in a StackPanel’s Resources property from the book Illustrated WPF. The XAML code is very simple as shown below. Below that is the code behind. This post is a continuation of Part 1.

<StackPanel Name="sp">
    <Button Name="btn1">Button 1</Button>
</StackPanel>

Below is the C# code.

namespace ResourcesCodeBehind
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // Add a silver Brush object to the Resources property of the StackPanel
            sp.Resources.Add("background", Brushes.Red);
            // Use the button’s FindResource method to search for the resource
            // and assign the result to the button’s Background property. 
            // Notice that the result of the search must be cast back
            // to the Brush type.
            btn1.Background = (Brush)btn1.FindResource("background");
        }
    }
}

The FindResource method starts at the current element and searches up the element tree querying each element’s Resources property with the given key. If it finds the resource, it returns its reference. Otherwise, it throws an exception. Notice also that the call to the FindResource method is on btn1. That’s because that’s where you want the search up the tree to begin.

TryFindResource

If the FindResource method doesn’t find the resource, it throws an exception. This probably isn’t what you want. To handle this situation more gracefully, you can use the TryFindResource method instead. This method returns null if it doesn’t find the resource.

btn1.Background = (Brush) btn1.TryFindResource( "background" );
if (btn1.Background == null) btn1.Background = Brushes.AliceBlue;

Indexer Syntax

In this example, since you knew exactly where the resource was, you didn’t actually have to use the FindResource method to search up the tree. You could have accessed the StackPanel’s ResourceDictionary directly, using the indexer syntax, using square brackets, as shown in the following line of code:

btn1.Background = (Brush) sp.Resources ["background"];

Find Resource or Try Find Resource

If the FindResource method or the TryFindResource methods get to the top of the element tree and haven’t found the resource, they try two more places before giving up—the Application object and the system resources.

Storing Resources in the Application Object

You can store a resource in the application object and use it just as if it had been stored in the UI element tree. Notice how you can get a reference to the Application object using the static Current method.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        SolidColorBrush myLightGreenBrush = Brushes.LightGreen;
        App application = (App)Application.Current; // Get the Application Object.
        application.Resources.Add("background", myLightGreenBrush);
        btn1.Background = (SolidColorBrush)btn1.FindResource("background");
        label.Background = (SolidColorBrush)label.FindResource("background");
    }
}

ResourcesApp

Here is what the application looks like. I have added a label. Both the button and the label have a light green background. So now this ‘background’ resource is available to all controls in the interface. You would, in production, use a better name than background. You may not wish to clutter your code too much with declaring these resources in code. You can put them into the XAML code instead. Here is how you would do that in the App.xaml file. I changed things a bit by adding a Silver colour and making the label background Silver.

<Application x:Class="ResourcesInApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ResourcesInApp"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <SolidColorBrush x:Key="background2" Color="Silver"/> <!-- just add this line -->
    </Application.Resources>
</Application>

I put a silver coloured resource in the application just by adding the one line shown above. Also, for the label in XAML, I change it to look for background2 instead of background.

ResourcesApp2

Resources in XAML

We could put our resources in XAML, in the Stack panel for example. The button and the label that is in the stack panel could reference the resource.

<StackPanel Name="sp">
    <StackPanel.Resources>
        <SolidColorBrush x:Key="background" Color="LightPink"/> 
    </StackPanel.Resources>

    <Button Name="btn1" Background="{StaticResource background}">Button 1</Button>
    <Label x:Name="label" Background="{StaticResource background}" >
        This is the text in a Label
    </Label>
</StackPanel>

Here is what the application looks like

ResourcesXAML

The next post will continue on with static resources in XAML. It will put the resource into the Window object, which is a better solution because it is located higher up the element tree and therefore more accessible from all of the elements in the window.

Series Navigation<< WPF Resources IntroductionWPF Resources Introduction Part 3 >>