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}" />
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.
There are a few important conventions/rules to follow here:
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.
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
.
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.
}
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));