Hi everyone. I'm Jordan Dimitrov from the WPF team. I'm planing to post about .Net, first with few post about WPF. My first post is about resources and themes.

Recently I had a problem with resources from themes files. I tried to use DynamicResource markup extension in Style in generic.xaml (sample bellow). But it didn't work. I changed DynamicResource extension with StaticResource markup extension and now it works. But WHY DynamicResource doesn't work?

Sample XAML

In my generic.xaml there are two items - a style for my CustomControl1 and a resource SolidColorBrush with key brush1.

    1 <ResourceDictionary

    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    4    xmlns:local="clr-namespace:WpfApplication1">

    5 

    6     <SolidColorBrush x:Key="brush1" Color="Red" />

    7 

    8     <Style TargetType="{x:Type local:CustomControl1}">

    9         <Setter Property="Template">

   10             <Setter.Value>

   11           <ControlTemplate TargetType="{x:Type local:CustomControl1}">

   12             <Border Background="{TemplateBinding Background}"

   13                     BorderBrush="{TemplateBinding BorderBrush}"

   14                     BorderThickness="{TemplateBinding BorderThickness}">

   15               <StackPanel>

   16                 <Button Height="100" Background="{StaticResource brush1}" />

   17                 <Button Height="100" Background="{DynamicResource brush1}" />

   18               </StackPanel>

   19             </Border>

   20                 </ControlTemplate>

   21             </Setter.Value>

   22         </Setter>

   23     </Style>

   24 </ResourceDictionary>

MainWindow.xaml

    1 <Window x:Class="WpfApplication1.Window1"

    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    4    xmlns:local="clr-namespace:WpfApplication1"

    5    Title="Window1" SizeToContent="WidthAndHeight">

    6     <StackPanel>

    7         <local:CustomControl1 />

    8     </StackPanel>

    9 </Window>

 

I check the MSDN documentation - Lookup behaviour for StaticResource extension and FindResource()/DynaminResource extension. (FindResource() method and DynamicResource extension have same lookup behaviour.) It's not very clear why DynamicResource doesn't work.

Static resource lookup behaviour FindResource()/DynaminResource lookup behaviour

1. The lookup process checks for the requested key within the resource dictionary defined by the element that sets the property.

2. The lookup process then traverses the logical tree upward, to the parent element and its resource dictionary. This continues until the root element is reached.

3. Next, application resources are checked. Application resources are those resources within the resource dictionary that is defined by the Application object for your WPF application.

1. The lookup process checks for the requested key within the resource dictionary defined by the element that sets the property.

    a. If the element defines a Style property, the Resources dictionary within the Style is checked  

    b. If the element defines a Template property, the Resources dictionary within the FrameworkTemplate is checked.

2.The lookup process then traverses the logical tree upward, to the parent element and its resource dictionary. This continues until the root element is reached.3. Next, application resources are checked. Application resources are those resources within the resource dictionary that is defined by the Application object for your WPF application.
4. Theme resource dictionary is checked, for the currently active theme. If the theme changes at runtime, the value is reevaluated.
5. System resources are checked.

 

Where is the problem?

Point 4 says that theme resource dictionary is checked. Actually it isn't search in whole dictionary, only in Style's Resources for the control (if exists). In my sample {DynamicResource brush1} searches in Resources of CustomControl1 Style not in the whole dictionary.

On the other side StaticResource extension lookup directly in xaml file. Internally it is using baml reader to find the resources in resource dictionaries.  This is because StaticResource extension process key during load time. Finally I understand what means:

Lookup behaviour 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.

Two other options:

  • If we want to use DynamicResource extension in control style we can add resources to another resource dictionary and add this resource dictionary to Style.Resources.

    8 <Style TargetType="{x:Type local:CustomControl1}">

    9         <Style.Resources>

   10             <ResourceDictionary>

   11                 <ResourceDictionary.MergedDictionaries>

   12                     <ResourceDictionary Source="common.xaml"/>

   13                 </ResourceDictionary.MergedDictionaries>

   14             </ResourceDictionary>

   15         </Style.Resources>

   16         ...

 I hope this will save you a little time while working with controls and resources.


About the Author

Hristo Maradjiev

Unit Manager,
Telerik XAML Team

Related Posts

Comments