Tuesday, March 1, 2011

How To define a Dependency Property

public static readonly DependencyProperty MyCustomProperty = DependencyProperty.Register("MyCustom", typeof(string), typeof(Window1));

public string MyCustom
{
get
{
return this.GetValue(MyCustomProperty) as string;
}
set
{
this.SetValue(MyCustomProperty, value);
}
}

You must have surprised why a dependency property is to be declared as static. Strange na…Smile with tongue out .That means it is related to class rather than object. But later on after reading about Dependency property, I came to know that a dependency property is maintained in class level, so you may say Class A to have a property B. So property B will be maintained to all the objects that class A have individually. The Dependency property thus creates an observer for all those properties maintained by class A and stores it there. Thus it is important to note that a Dependency property should be maintained as  static.

 

A static read-only field can only be set in the field definition itself or in a static constructor.

 

Defining a dependency property


public static readonly DependencyProperty FontSizeProperty;


 


Creating or Registering a Dependency Property


Generally, a class creates an object of type DependencyProperty by a call to the static DependencyProperty.Register method, which may look something like this:

FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double),
typeof(Control));




The arguments are the text name of the property associated with the dependency property, the data type of the property, and the class type registering the property. In actuality, there's usually some more code involved. The DependencyProperty object often includes metadata that describes some crucial aspects of the property.

 

GetValue and SetValue


Where do the SetValue and GetValue methods come from? These methods are defined in the DependencyObject class from which much of the WPF descends:

Object
----DispatcherObject (abstract)
--------DependencyObject
------------Visual (abstract)
--------------------UIElement
-----------------------------FrameworkElement
------------------------------------Control

Watch out for similar names: Both DependencyObject and DependencyProperty are classes. Many classes in the WPF descend from DependencyObject and thus have SetValue and GetValue methods. These methods work with fields defined as static DependencyProperty objects.

Even though the DependencyProperty object passed to the SetValue and GetValue methods is static, SetValue and GetValue are instance methods, and they are setting and obtaining values associated with the particular instance. The DependencyObject is maintaining the current value, and handling all the routine stuff as well. For example, if SetValue hasn't yet been called for the particular Control instance, GetValue returns the value of the DefaultValue property associated with the metadata of FontSizeProperty.

When a program such as SetFontSizeProperty sets the FontSize property, the SetValue method has some work to do. The method must call the validation method to determine if the value is proper. If not, it throws an exception. Because the AffectsMeasure flag is set for FontSizeProperty, the SetValue method must cause a recalculation in the size of the control, which also requires the control to be redrawn. That redrawing logic uses the new FontSize in displaying text. (For a property like Foreground, the AffectsMeasure flag is false but the AffectsRender flag is true. The control isn't resized, but it is redrawn.) The SetValue method must also pass the new value down through the tree as a result of the Inherits flag. Elements in the tree can accept that new value for themselves, or reject it if their own FontSize property has been explicitly set.

Although examining how the FontSize property works is certainly helpful in understanding dependency properties, the lessons are hammered home only when you define a dependency property on your own.

The class that follows inherits from Button but includes a new dependency property. This class is called SpaceButton, and before you get ideas about launching buttons into orbit, you should know that the SpaceButton merely displays text with spaces inserted between each letter. SpaceButton adds two properties to those found in the normal Button class: Text and Space. For contrast, the class implements the Text property as a traditional .NET property, while the Space property is implemented in conjunction with a dependency property. The SpaceButton sets its Content property to the Text string with spaces inserted as indicated by the value of the Space property.

 

Naming Convention


The naming convention of a dependency property states that it should have the same wrapper property which is passed as the first argument. Thus in our case, the name of the Wrapper "MyCustom" which we will use in our program  should be passed as the first argument of the Register method, and also the name of the Dependency property should always be suffixed with Property to the original Wrapper key. So in our case the name of the Dependency Property is MyCustomProperty. If you dont follow this, some of the functionality will behave abnormally in your program.

It should also be noted that you should not write your logic inside the Wrapper property as it will not be called every time the property is called for. It will internally call the GetValue and SetValue itself. So if you want to write your own logic when the dependency property is fetched, there are callbacks to do them.

No comments:

Post a Comment