Wednesday, June 25, 2008

Static vs Dynamic Resources

In WPF you can use either reference a resource statically or dynamically. Most documentation floating around was fairly vague on what each system gave except for there was a slight performance penalty of choosing to access a resource dynamically. One analogy is that Static is like compile time look up and Dynamic is like run time. Terrible analogy.

Using StaticResource will evaluate the resource once, the first time that access is made i.e. Not at compile time.

Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.

A DynamicResource will be evaluated every time the resource is required.

Provides a value for any XAML property attribute by deferring that value to be a reference to a defined resource. Lookup behavior for that resource is analogous to run-time lookup.

So when would either be used? Considering performing a resource lookup dynamically carries a higher cost, you would prefer to use StaticResource. However what benefits does dynamic look up bring? Basically if you want to perform Skinning or any other type of system that could change the resource after it has been loaded then you should use Dynamic resolution. Now if that is just not the case for your WPF application then just stick with StaticResources. However I think that might be a wee bit short sighted.

As a guideline I believe that anything in the immediate context can be referenced statically. This basically includes any resources defined in the same XAML file that references them. If the resource is defined externally to the XAML file then Dynamically reference it.

   1:  <Window.Resources>
   2:    <local:EnumValueToDescriptionConverter x:Key="enumValueConverter"/>
   3:  </Window.Resources>
   4:  <ListView 
   5:       ItemsSource="{Binding Path=Users}"
   6:       ItemContainerStyleSelector="{DynamicResource myStyleSelector}" >
   7:    <ListView.View>
   8:      <GridView>
   9:        <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" />
  10:        <GridViewColumn Header="UserName" DisplayMemberBinding="{Binding Path=UserName}" />
  11:        <GridViewColumn Header="Status" DisplayMemberBinding="{Binding Path=Status, Converter={StaticResource enumValueConverter}}" />
  12:      </GridView>
  13:    </ListView.View>
  14:  </ListView>

Here we define an Enum Converter on line 2 and reference it statically on line 11. The style reference in line 6 refers to a style external to the XAML file so I reference it dynamically.

4 comments:

James Miles said...

Hi Lee,

Correct me if I’m wrong. But isn’t it also important to note that there is a difference in how the compiler treats the two.

The existence of a static resource is enforced by the compiler where as a dynamic resource is not? Not unlike the following example;

class Program
{
static void Main(string[] args)
{
Console.WriteLine(Resources.AStaticResource);
Console.WriteLine((Resources.DynamicResources.ContainsKey("ADynamicResource") ? Resources.DynamicResources["ADynamicResource"] : null));
}
}

static class Resources
{
public static string AStaticResource = "Hello Static World";

public static Dictionary>string, string< DynamicResources = new Dictionary>string, string<();
}

Personally, I’d want to be sure that I do want to change something at runtime before making it dynamic. Essentially, StaticResource is a more robust but less powerful way of referencing a resource.

Cheers,
James

James Miles said...

Correction.

I just realised, the existence of a static resource isn't checked at compile time at all.

The designer throws these errors!

The compiler doesn't evaluate resources at all, dynamic or static.

James Miles said...

So there is actually a difference in the runtime resolution of resources. If at runtime the framework can’t find;

Static Resource – throws exception
Dynamic Resource – nothing

Lee Campbell said...

Yeah, your last 2 comments are correct James. I still stand by my recommendation on "reference static if local, else dynamically".