In this article, we are going the explore how to create dependency properties. Dependency properties with a special property information that allows the WPF system to interact with them through the XAML code. They also need to be implemented in a specific way because of how WPF interacts with them. As an example, we are going to construct a button that has the capability of displaying a specific message. This message can be set through a dependency property from the XAML code. You can find the example code at https://github.com/atzimler/WpfWednesday, the example application is in the Z06_DependencyProperties subdirectory.
The HelloMessageButton class
This class is going to be the actual button placed on the Window from the XAML code. It is derived from the Button class. Here is its source code:
Let’s walk through the code.
Our class is derived from the Button class, so that we inherit the behavior of it. Remember, you should select your base class on behavior, not on look and feel. The reason behind this is that the latter is easier to change than the former.
The message property is a type safe way to access the property that WPF knows about. These properties should only contain the call to GetValue and SetValue methods. In case of GetValue, you should cast the return type from object to the actual type. The reason behind why you should only have these lines here and nothing else is that the WPF system will not access the property through these get and set accessors. It will directly call the relevant GetValue and SetValue methods, so if you place anything else here, your class will behave differently when called from the code and the XAML. In later articles, we will explore how to add additional functionalities that we would normally put into our setter methods.
In the WPF system, it is a convention to have the dependency property information with the same name as the property, but appending “Property” to it. This line instructs the WPF system to register a dependency property for the HelloMessageButton class with a type of string named Message. The nameof operator is just creating the string “Message” from the compiler token Message during compile time. It is a best practice to not to encode property names as string, so when you rename it the reference string will be updated to the new name. The PropertyMetadata object passed as the last parameter to the call describes several attributes of the property. In this case, we only specify that the initial value of this property should be null. Pay attention to have this member as static member, otherwise the WPF will try to register the property for every instance of your class and that will result in run time exception. A specific dependency property can only be registered once.
Finally, the above lines just register a click event handler, so when the button is pressed we display the value of the Message property.
Let’s test it
We will use a simple window from a XAML code to display the button and set it up.
Compile and run, click on the button. If you remove, the Message property from the above XAML code, you will see an empty message box showing up. If then you change the null in the PropertyMetadata during the registration to some other string, you will see that string if you don’t change the Message property from the XAML code.
Now that we have our first dependency property defined, next time we are going to explore how to execute additional logic when the WPF system changes the value of the property.