Sunday, December 26, 2010

Order in Chaos: Dependency Property Value Resolution

One of the strength points for WPF is the ability to set a property value using a wide range of methods.
Unfortunately, this variety makes it hard to understand how a WPF dependency property gets its final value. Hopefully this post will help organize this issue.
This post is based on the comprehensive MSDN article “Dependency Property Value Precedence”.
Can you show an example please?
In order to see this in action let’s create a WPF application that has all these scenarios used.
For this to be possible we will create a custom control named MyCustomControl and add it a dependency property named MyValue which we’ll use for setting values from different places.
To see the actual value at runtime we will present this property in a TextBlock. In fact, our custom control will have just that in his control template.

Step 1 – Default Value

First we add our dependency property and set its default value to “1”.

public string MyValue
{
   get { return (string)GetValue(MyValueProperty); }
   set { SetValue(MyValueProperty, value); }
}
public static readonly DependencyProperty MyValueProperty =
   DependencyProperty.Register("MyValue", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata("1"));
After setting the default control template (Themes\Generic.xaml) as follows:
<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:DependencyPropertyValueResolutionDemo">
   <Style TargetType="{x:Type local:MyCustomControl}">
       <Setter Property="Template">
           <Setter.Value>
               <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
                   <TextBlock
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       FontSize="32"
                       Text="{TemplateBinding MyValue}" />
               </ControlTemplate>
           </Setter.Value>
       </Setter>
   </Style>
</ResourceDictionary>
And the main window to:
<Window x:Class="DependencyPropertyValueResolutionDemo.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:local="clr-namespace:DependencyPropertyValueResolutionDemo"
       Title="MainWindow" Height="150" Width="150">
   <Grid>
       <local:MyCustomControl />

Read more: Arik Poznanski's Blog