WPF - Dependency Properties
In .Net 1.1/2.0, a typical CLR property looks like this,
For a regular CLR property, the property value is read directly from a private class member. WPF introduces a new construct called a dependency property, which can get its value from different sources and the actual value resolution occurs dynamically at run-time based on some precedence rules.
For example, a TextBox‘s Text property, which is a dependency property, can get its value from a style, a trigger, an animation, or locally (among others). Consider the following XAML,
If we observe closely in above sample, the TextBox‘s Text (dependency) property is set in three places. So which one applies? If we run this, the TextBox starts out with the text "Local value text", even though we’ve set a Style that says Text should be "Property setter text". Why? This is because, when the WPF property system tried to resolve the Text value at run-time, the local value has precedence over a Style setter.
The precedence rules are (higher to lower),
Now say we want to remove the dependency property’s local value so that the Text value can come from elsewhere (like a Style). The local value can be erased by,
Once the local value is erased, you’ll see the Text changed to "Property setter text", and mouse over text to "Trigger setter text". Thus, the Text (dependency) property can get its value from different sources (local, style, trigger), and the run-time value depends a set of precedence rules. See the example, how to create dependency property?
Dependency properties can also be read-only. A dependency property can only be created on a class which derives from the DependencyObject class, but since this class is very high up the WPF class hierarchy, this is not much of a concern.
Some of the advantages of dependency properties are,
// Private field private int _postId; // Public property that wraps the private field public int PostId{ get { return _postId; } set { _postId= value; } }
For a regular CLR property, the property value is read directly from a private class member. WPF introduces a new construct called a dependency property, which can get its value from different sources and the actual value resolution occurs dynamically at run-time based on some precedence rules.
For example, a TextBox‘s Text property, which is a dependency property, can get its value from a style, a trigger, an animation, or locally (among others). Consider the following XAML,
<Grid.Resources> <Style x:Key="TextBoxBaseStyle" TargetType="TextBox"> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Text" Value="Trigger setter text" /> </Trigger> </Style.Triggers> <Setter Property="Text" Value="Property setter text" /> </Style> </Grid.Resources> <!-- The local value of the Text property is set here --> <TextBox x:Name="MyTextBox" Height="30" Width="100" Text="Local value text" Style="{StaticResource TextBoxBaseStyle}" />
If we observe closely in above sample, the TextBox‘s Text (dependency) property is set in three places. So which one applies? If we run this, the TextBox starts out with the text "Local value text", even though we’ve set a Style that says Text should be "Property setter text". Why? This is because, when the WPF property system tried to resolve the Text value at run-time, the local value has precedence over a Style setter.
The precedence rules are (higher to lower),
- Active animations
- Local value
- Style triggers
- Style setters
- Theme style
- Inheritance
- Default value (from dependency property metadata)
Now say we want to remove the dependency property’s local value so that the Text value can come from elsewhere (like a Style). The local value can be erased by,
this.MyTextBox.ClearValue(TextBox.TextProperty); // Note that these, will not remove the local value because // we're still setting a local value (to empty or null). //this.MyTextBox.Text = string.Empty; //this.MyTextBox.Text = null;
Once the local value is erased, you’ll see the Text changed to "Property setter text", and mouse over text to "Trigger setter text". Thus, the Text (dependency) property can get its value from different sources (local, style, trigger), and the run-time value depends a set of precedence rules. See the example, how to create dependency property?
// A dependency property is usually wrapped in a regular CLR property. This wrapper is not necessary, // we can directly call GetValue/SetValue, but it’s useful if the dependency property needs to be set via XAML. // Note that at runtime WPF calls the underlying GetValue/SetValue methods directly, bypassing the wrappers. public int MyValue { get { return (int)GetValue(MyValueProperty); } set { SetValue(MyValueProperty, value); } } // A dependency property definition public static readonly DependencyProperty MyValueProperty = DependencyProperty.Register( "MyValue", // Name of the dependency property typeof(int), // Type of the dependency property typeof(MyClass), // Type of the owner new PropertyMetadata( 0, // The default value of the dependency property new PropertyChangedCallback(OnValueChanged), // Callback when the property changes new CoerceValueCallback(CoerceValue)), // Callback when value coercion is required new ValidateValueCallback(IsValidValue)); // Callback for custom validation // The validation callback private static bool IsValidValue(object value) { /* Validate the set value */ } // The coercion callback private static object CoerceValue(DependencyObject d, object value) { /* Adjust the value without throwing an exception */ } // The value changed callback private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { /* Called every time the dependency property value changes */ }
Dependency properties can also be read-only. A dependency property can only be created on a class which derives from the DependencyObject class, but since this class is very high up the WPF class hierarchy, this is not much of a concern.
Some of the advantages of dependency properties are,
- XAML friendly: Dependency properties can be set in XAML (via a CLR property wrapper)
- Change notifications and validation: Get change notifications and validate property values by registering callbacks.
- Value inheritance: Dependency property values can be inherited from up the logical tree.
- Reduced memory: Since dependency properties are static, they save per-instance memory compared to regular CLR properties (which are based on per instance fields).
// We have to hook into TextBox’s Text property. DependencyPropertyDescriptor textDescr = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox)); if (textDescr != null) { textDescr.AddValueChanged(myTextBox, delegate { // Add your property changed logic here... }); }
An example cannot be any better than this one. Loved the way its demonstrated here. Full marks.
ReplyDeleteMany articles saying that DP value resolve dynamically but no one has provided example. Excellent explanation given here with example how DP resolve dynamically. Also got that answer of why trigger changes are temporary. Good one, Keep it up Man :)
ReplyDeleteSimple and to the point. well done. pls keep posting.
ReplyDeleteHI explanation is goood but its not working for setting the text using style.
ReplyDeleteIt will work while removing the Text="Local value text"
ReplyDelete
ReplyDeleteAll are saying the same thing repeatedly, but in your blog I had a chance to get some useful and unique information, I love your writing style very much, I would like to suggest your blog in my dude circle, so keep on updates.
SAP training in Chennai
First is to thank you for all this informative posts you give us for free; i bet all of us are happy.
ReplyDeleteSuch a great idea of yours! You have been a big help for me. Thanks a lot. more post for interesting topic. Great!
SAP training in Chennai
This article creates a new hope and inspiration with in me. Thanks for sharing article like this. The way you have stated everything above is quite awesome. Keep blogging like this. Thanks.
ReplyDeleteSAP training in Chennai
This is the best way to explain Dependency properties in WPF.Lot of other blogs are there regarding this but none has able to explain it so easily. Thanks a lot. Do post this kind of simplified explanations.
ReplyDeleteMy Arcus offer java training with 100% placement. Our java training course that includes fundamentals and advance java training program with high priority jobs. java j2ee training with placement having more exposure in most of the industry nowadays in depth manner of java .
ReplyDeletejava training in chennai
nice copy and paste article
ReplyDeletewho is the dumb sob unit inch goat humper who posted this crap
sure love the source code project available for download rofl
Excellent post! Thank you for Sharing. We are the best erp software providers in chennai. For more details call +91 9677025199 or email us on info@bravetechnologies.in
ReplyDeleteerp in chennai
Thank you for taking time to provide us some of the useful and exclusive information with us.
ReplyDelete