Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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.</p> <p>A dependency property is a property on one object whose value <em>depends</em> on some <em>other</em> object. So, for instance:</p> <ul> <li><p>The value of the <code>FontFamily</code> property of a <code>TextBox</code> can (and usually does) depend on the <code>FontFamily</code> property of its container. If you change the property on the container, the value on the <code>TextBox</code> changes.</p></li> <li><p>The value of the <code>Text</code> property of a <code>TextBox</code> can depend on a bound data source. When the value of the bound property changes, the value of the <code>Text</code> property changes.</p></li> <li><p>The value of the <code>Opacity</code> property of a <code>Label</code> 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.</p></li> <li><p>The value of all kinds of properties on any UI element can depend on the style that you've applied to them.</p></li> </ul> <p>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.</p> <p>When the <code>TextBox</code>, or the thing that's rendering it, needs to know what its <code>FontFamily</code> is, the <code>FontFamily</code> getter calls the <code>GetValue</code> method. That method finds the value from the container, or animation, or binding, or whatever.</p> <p>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. </p> <p>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 <code>GetValue</code> 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.</p> <p>Since that metainformation is the same for every object in the class (i.e., <code>TextBox.Text</code> works the same for every <code>TextBox</code>), the dictionary it's stored in is a static property of the class.</p> <p>So when you see code like this:</p> <pre><code>static Button() { // Register the property Button.IsDefaultProperty = DependencyProperty.Register("IsDefault", typeof(bool), typeof(Button), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsDefaultChanged))); } </code></pre> <p>what's happening is that the metainformation that defines the <code>IsDefault</code> property on all <code>Button</code> objects is being added to that dictionary. And when you see this:</p> <pre><code>public bool IsDefault { get { return (bool)GetValue(Button.IsDefaultProperty); } set { SetValue(Button.IsDefaultProperty, value); } } </code></pre> <p>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. </p> <p>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 <code>SetValue</code> 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 <code>TextBox</code> to display text in <code>Consolas</code> irrespective of what the other controls in the window are using.").</p> <p>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 <code>TextBox</code> controls and add them to a <code>Window</code>, not one of them actually contains a reference to a <code>FontFamily</code> 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 <code>TextBox</code> has 100 dependency properties (and it does, just about), whenever you create a <code>TextBox</code>, 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.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload