wpf Standard dependency properties


Example

When to use

Virtually all WPF controls make heavy use of dependency properties. A dependency property allows for the use of many WPF features that are not possible with standard CLR properties alone, including but not limited to support for styles, animations, data binding, value inheritance, and change notifications.

The TextBox.Text property is a simple example of where a standard dependency property is needed. Here, data binding wouldn't be possible if Text was a standard CLR property.

<TextBox Text="{Binding FirstName}" />

How to define

Dependency properties can only be defined in classes derived from DependencyObject, such as FrameworkElement, Control, etc.

One of the fastest ways to create a standard dependency property without having to remember the syntax is to use the "propdp" snippet by typing propdp and then pressing Tab. A code snippet will be inserted that can then be modified to suit your needs:

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

    // Using a DependencyProperty as the backing store for MyProperty.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0));
}

You should Tab through the different parts of the code snippet to make the necessary changes, including updating the property name, property type, containing class type, and the default value.

Important conventions

There are a few important conventions/rules to follow here:

  1. Create a CLR property for the dependency property. This property is used in your object's code-behind or by other consumers. It should invoke GetValue and SetValue so consumers don't have to.

  2. Name the dependency property correctly. The DependencyProperty field should be public static readonly. It should have a name that corresponds with the CLR property name and ends with "Property", e.g. Text and TextProperty.

  3. Do not add additional logic to CLR property's setter. The dependency property system (and XAML specifically) does not make use of the CLR property. If you want to perform an action when the property's value changes, you must provide a callback via PropertyMetadata:

    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0, MyPropertyChangedHandler));
    
    private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        // Use args.OldValue and args.NewValue here as needed.
        // sender is the object whose property changed.
        // Some unboxing required.
    }
    

Binding mode

To eliminate the need for specifying Mode=TwoWay in bindings (akin to the behavior of TextBox.Text) update the code to use FrameworkPropertyMetadata instead of PropertyMetadata and specify the appropriate flag:

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), 
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));