I have read about dependency properties a lot on SO and other sites. But, really haven't found a great explanation and am still confused. I use both SL and WPF. Are they different in SL and WPF, in terms of implementation? Why do we really need them? Are they static means that their values are shared? Why was the reason MS introduced dependency properties?
Advantages of a Dependency Property The Dependency Property stores the property only when it is altered or modified. Hence a huge amount of memory for fields are free. It means that if no value is set for the property then it will return to the inheritance tree up to where it gets the value.
Dependency properties are used when you want data binding in a UserControl , and is the standard method of data binding for the WPF Framework controls. DPs have slightly better binding performance, and everything is provided to you when inside a UserControl to implement them.
The answer is in the name itself, though the word "dependency" is so fraught with meaning in software development that it's not especially clear what that means.
A dependency property is a property on one object whose value depends on some other object. So, for instance:
The value of the FontFamily
property of a TextBox
can (and usually does) depend on the FontFamily
property of its container. If you change the property on the container, the value on the TextBox
changes.
The value of the Text
property of a TextBox
can depend on a bound data source. When the value of the bound property changes, the value of the Text
property changes.
The value of the Opacity
property of a Label
can depend on an animation storyboard, in the common scenario where you've set up a UI element to fade in or fade out in response to some event.
The value of all kinds of properties on any UI element can depend on the style that you've applied to them.
The central concept behind dependency is that the thing that's depending should get the property value from the thing it's depending on. This is why a dependency property is implemented as a CLR property whose getter calls a method.
When the TextBox
, or the thing that's rendering it, needs to know what its FontFamily
is, the FontFamily
getter calls the GetValue
method. That method finds the value from the container, or animation, or binding, or whatever.
There's a lot of complexity in that method. If the value's inherited, for instance, it works in a way that's pretty analogous to how WPF finds styles in a resource dictionary: it looks in a local dictionary to find the value, and if there's no entry it looks in its parent's dictionary, and so on all the way up until it finds a value or reaches the top of the hierarchy, in which case it uses a default value.
If you look at the implementation of dependency properties, that's what you'll find. A dependency object has a dictionary that may or may not contain an entry for a given property. The GetValue
method gets values from that dictionary (which is how objects with dependency properties can have local values that override what they're inheriting from), and if it doesn't find the value, it uses the metainformation about the property to figure out where it should look.
Since that metainformation is the same for every object in the class (i.e., TextBox.Text
works the same for every TextBox
), the dictionary it's stored in is a static property of the class.
So when you see code like this:
static Button()
{
// Register the property
Button.IsDefaultProperty =
DependencyProperty.Register("IsDefault",
typeof(bool), typeof(Button),
new FrameworkPropertyMetadata(false,
new PropertyChangedCallback(OnIsDefaultChanged)));
}
what's happening is that the metainformation that defines the IsDefault
property on all Button
objects is being added to that dictionary. And when you see this:
public bool IsDefault
{
get { return (bool)GetValue(Button.IsDefaultProperty); }
set { SetValue(Button.IsDefaultProperty, value); }
}
what you're seeing is the getter method that looks up the property's value (from the local dictionary, the parent object, or whatever) based on that metainformation.
Remember how I said that the first place the getter looks to find a property's value is in the object's local dictionary? The SetValue
method in the setter is how that entry gets added to the dictionary (if it's ever called, which it will only be if you're overriding the dependency by explicitly setting the property, i.e. saying "I want this TextBox
to display text in Consolas
irrespective of what the other controls in the window are using.").
A hugely significant benefit that we get from this kind of apparently-complex system is that dependency properties on objects only consume memory if they're set. If I create 10,000 TextBox
controls and add them to a Window
, not one of them actually contains a reference to a FontFamily
object. That's 10,000 object references that I'm not allocating memory for, and that the garbage collector isn't checking. In fact, if a TextBox
has 100 dependency properties (and it does, just about), whenever you create a TextBox
, that's 100 backing fields you aren't allocating memory for. Dependency properties only consume memory if you explicitly set them. Since the vast majority of properties on UI objects never get explictly set, these are fantastic savings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With