Sunday, September 1, 2013

How to create a dependency property


What is dependency Property? Read my post : Difference between the dependency property and clr-property

Code Example Download
Below are the steps to create dependency property

1) Defining a Dependency Property
2) Registering a Dependency Property
3) Adding a property wrapper

Defining a Dependency Property

First step is to define the DP ,it is the instance of DP class
  
 public class xTextBox : TextBox
    {

        public static readonly DependencyProperty MinNumProperty ;

}
Note: You can add dependency property only to those classes that drive from Dependency Object.
Define a static field of DependencyProperty Object in the associated class.
The field is defining read only which can be set only in the static constructor for the associated class.
Conventionally, the field that defines the dependency property has the name of ordinary property plus the word ‘Property’ at the end.
In the first step define the object of dependency property class.

Registering a Dependency Property

After defining Dependency Property, we need to register the Dependency Property with WPF.
DependencyProperty object can not be instantiated directly because DependencyProperty Class has no public constructor. So for creating the DependencyObject instance use the static method DependencyProperty.Register() .

DependencyProperty objects can not be changed after they are created because all DependencyProperty object are read only. Instead, their values must be supplied as arguments to the Register() method.

MinNumProperty =
           DependencyProperty.Register("MinNum", typeof(int), typeof(xTextBox), new
           FrameworkPropertyMetadata(new Int32(),
           FrameworkPropertyMetadataOptions.AffectsArrange));


There are two steps of registering a dependency property.
                a) Create a FrameworkPropertyMetadata object
                                It indicate what services you want to use with your dependency Property
(Such as support for data binding, animation, and journaling).
                b) Call the static DependencyProperty.Register() method to register.

Adding a property wrapper

Finally wrap the Dependency property to the .Net CLR- property to access it.
There are two methods SetValue() and GetValue() that are defined in the base
DependencyObject class.


public int MinNum
        {
            get
            {
                return (Int32)GetValue(xTextBox.MinNumProperty);
            }
            set
            {
                SetValue(xTextBox.MinNumProperty, value);
            }
        }
In the property wrapper just call SetValue() and GetValue() method. You should not add extra code to validate values, raise events, and so on.

Note: The property wrapper is not the right place to validate data or raise an event. We should use dependency property callbacks. For the validation purpose we should use DependencyProperty.ValidateValueCallback.
Now we can use this dependency property now:

txtTest.MinNum = 2;

There are three callbacks provided by the Dependecy Property

  • ValidateValueCallback
  • CoerceValueCallback
  • PropertyChangeCallback

The first two ValidateValueCallback and CoerceValueCallback should be use for Property validation.
These two could prevent invalid value.

ValidateValueCallback In this Validation callback you can check if the value is valid or not. If it returns true means value is valid otherwise a exception ‘ArgumentException’ will be thrown.


private static bool OnValidateValueCallback(object data)
        {
            return data is Int32;
        }


CoerceValueCallback  Suppose the Property value is valid but it is not acceptable e .g. you need to enter integer  value between 0 to 8 but you enter 9, the 9 is valid integer value but it is not acceptable. So CoerceValueCallback allow you to adjust the value.

 private static object OnCoerceValueCallback(DependencyObject sender, object data)
        {
            if ((int)data < 0 || (int)data > 8)
            {
                return 0;
            }

            return (int)data;
        }

PropertyChangeCallback PropertyChangeCallback is a method and called every time as property value gets changed, in the event argument there is old and new value.
At this point you can raise a change event if you want to provide the notification to other class

private static void OnPropertyChangeCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            MessageBox.Show("CallBack Call--" + " Old value: " + e.OldValue + ", New value: " + e.NewValue + ", Property: " + e.Property);
        }



PropertyChangeCallback and CoerceValueCallback are use with FrameworkPropertyMetadata

And ValidateValueCallBack is use with DependencyProperty.Register()

public static readonly DependencyProperty MinNumProperty =
            DependencyProperty.Register("MinNum", typeof(int), typeof(xTextBox), new
            FrameworkPropertyMetadata(new Int32(),
            FrameworkPropertyMetadataOptions.AffectsArrange, new PropertyChangedCallback(OnPropertyChangeCallBack), new CoerceValueCallback(OnCoerceValueCallback)), new ValidateValueCallback(OnValidateValueCallback));