How to Create a Custom Dependency Property


Hello Everyone!

Today I’m going to talk about how to create a Custom Dependency Property for use within WPF.  When used with creating custom controls they can be used to extend the functionality of the control.  They can be used for many other reasons but for now we are going to stick within the context of using them for a control.

Lets say were going to build a sort of Watermark text functionality into a TextBox control.  This will allow a developer to specify a string of light gray text that should be shown when no text is present and the control doesnt have any form of focus.  Well the first thing we will need is a custom property on the TextBox control to store this text in.  This is the perfect place to use a DependencyProperty.

First lets create our class.

public class WatermarkedTextBox : TextBox
{
    static WatermarkedTextBox()
    {

        DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkedTextBox),
new FrameworkPropertyMetadata(typeof(WatermarkedTextBox)));
    }
}

Next were going to use yet another wonder snippet provided by Visual Studio called propdp.

If we type in propdp and hit tab twice we will see this appear.

public int MyProperty
{
    get { return (int)GetValue(MyPropertyProperty); }
    set { SetValue(MyPropertyProperty, value); }
}

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new UIPropertyMetadata(0));

This should be very familiar from my previous blog on WPF Attached Properties.  We are going to tab through and the the property type to string, the property name to WatermarkText, the ownerclass to WatermarkedTextBox, and the default value to string.empty.

Our property should now look like so

public string WatermarkText
{
    get { return (string)GetValue(WatermarkTextProperty); }
    set { SetValue(WatermarkTextProperty, value); }
}

public static readonly DependencyProperty WatermarkTextProperty =

    DependencyProperty.Register("WatermarkText", typeof(string), typeof(WatermarkedTextBox),
new UIPropertyMetadata(string.Empty));

And that is it!  We now have ourselves a custom dependency property that we can use to store the text intended for the watermark functionality.  Now we can use things like TemplateBinding inside of our templates for this control to bind an elements Text or Content property to this.  This could be a label, maybe an adorner, there are many ways this can be used.  And because its a DependencyProperty we can take full advantage of what WPF provides like the Binding system, setting from Styles and if the return type were one that is animateable like double then we could also animate it.

There are a few things to note about creating a DependencyProperty.  Sometimes people like to put logic into property setters for functionality when that property has changed.  When we use a DependencyProperty the setter of the actual property that wraps the call to SetValue, does not always get called.  If something changes the property in the dependency system behind the scenes then your code is never run.

Luckilly we have a nice solution for this!  There are two different ways we can still provide this functionality.

The first way we can do this is by applying a delegate to be a PropertyChanged handler for the dependency property.  We have another constructor parameter in the UIPropertyMetadata object that will accept this delegate.  When we apply it, it should appear as shown.

public string WatermarkText
{
    get { return (string)GetValue(WatermarkTextProperty); }
    set { SetValue(WatermarkTextProperty, value); }
}

public static readonly DependencyProperty WatermarkTextProperty =

    DependencyProperty.Register("WatermarkText", typeof(string), typeof(WatermarkedTextBox),

                                 new UIPropertyMetadata(string.Empty, OnWatermarkTextChanged));



public static void OnWatermarkTextChanged(DependencyObject box, DependencyPropertyChangedEventArgs e)
{
     //Add changed functionality here
}

The second way to do this is by overriding OnPropertyChanged.  Any class that inherits from DependencyObject will automatically have this override available to them.  This method accepts DependencyPropertyChangedEventArgs e that will provide us the property that has changed, the new value, and the old value.  This is one way we might implement this.

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
    base.OnPropertyChanged(e);

    if (e.Property == WatermarkedTextBox.WatermarkTextProperty)
    {
        //add changed functionality here
    }
}

There are many other things we can do with a DependencyProperty and to get more information please check out the MSDN page on How to: Implement a Dependency Property.

I hope this article helps and have a good day!

Comments are closed.