Typically, read-only Dependency Properties are most commonly found in custom controls in situations where we need to data bind to a value, but do not want it to be publicly accessible. It might be a property that holds some relation to an on screen visual, a mid calculation point, or previous value, but generally, we don't want the users of our framework to be able to data bind to it.
Let's imagine a scenario where we want to create a button that will enable us to set a tooltip message to display when the control is disabled, in addition to the normal tooltip message. In this case, we could declare one Dependency Property to hold the disabled tooltip message and another to store the value of the original tooltip when displaying the disabled tooltip. This original tooltip property is a perfect candidate to be a read-only Dependency Property. Let's see what this property looks like:
private static readonly DependencyPropertyKey originalToolTipPropertyKey = DependencyProperty.RegisterReadOnly("OriginalToolTip", typeof(string), typeof(TooltipTextBox), new PropertyMetadata()); public static readonly DependencyProperty OriginalToolTipProperty = originalToolTipPropertyKey.DependencyProperty; public static string GetOriginalToolTip(DependencyObject dependencyObject) { return (string)dependencyObject.GetValue(OriginalToolTipProperty); }
As you can see, we use a different syntax to declare read-only Dependency Properties. Instead of returning the DependencyProperty identifier that is returned from the Register method, the RegisterReadOnly method returns a DependencyPropertyKey object.
This object is typically declared with a private access modifier, to stop it from being externally used with the DependencyObject.SetValue method. However, this method can be used within the class that registered the read-only property to set its value.
The DependencyProperty property of the DependencyPropertyKey object is used to return the actual DependencyProperty identifier that is used to access the property value from the dictionary that we discussed earlier.
The input parameters of the RegisterReadOnly methods offer the same options as those of the standard Register method, although there is one less overload. Unlike the Register method, when calling the RegisterReadOnly methods, we always need to provide the PropertyMetadata object, although we can pass a null value if we do not need what it provides.
One very important point to note is that when data binding to a read-only Dependency Property, we must set the binding Mode property to the OneWay enumeration member. Failure to do so will result in an error at runtime. We've now covered the creation of normal Dependency Properties in some detail, so let's move on to take a look at a different kind Dependency Property.