What is a dependency property?
|
One of the things that have puzzled me most about WPF was the Dependency Property. So many explanations have been made about what they do and why they exist that the in-a-nutshell version of the principles behind them have been lost in the chatter. I believe that the essential information to grasp is this: Firstly, Dependency properties are there to enable declarative code, XAML, to alter the properties of an object. They are, if you will, the attributes of the XML elements that make up your user interface. Secondly, Dependency properties reduce the data requirements of what are essentially light graphical objects. They rely on the fact that most properties will never be set explicitly, so, if a property is not set, why store any data for it? Lastly, dependency properties enable dynamic applications because of a powerful notification system that can inform the program of changes to data and user-interface elements in a very specific way. How do they work? If you've ever written a WPF control you'll probably have read and followed the code samples for adding your own dependency property with a static DependencyProperty, the optional accessor and the optional change notification handler. What isn't made clear in any of the documentation I've read so far is that the DependencyProperty object which is static and readonly in the code is not where the information is stored. This is in fact simply a key, a unique reference, used to find the actual data in a dictionary of objects stored in the instance of a DependencyObject. This is the "Sparse Storage" mechanism, alluded to in various publications, that enables two important functions. Firstly, if a DependencyProperty has never been set, the default value, which is statically associated with the key, can be applied to any instance of a Dependency object requiring it. This drastically reduces the memory footprint of a system that is built to have many thousands of active graphical objects on screen at once. Secondly, this style of storage permits the use of the "Attached Property" such as Canvas.Top or Grid.Column. The reason this works is because each instance of the DependencyObject derived classes maintain their own dictionary of properties and the keys are unique for each class so, even if an object has a "Top" property it will never be confused with "Canvas.Top" The design of the DependencyObject and the implementation of Dependency Properties are of course a classic implementation of the Flyweight Pattern that enables many objects to share standard properties or default information while allowing any non-default information to be stored along with the instance that needs it.
|