How to override metadata for a dependency property (WPF .NET)

When you derive from a class that defines a dependency property, you inherit the dependency property and its metadata. This article describes how you can override the metadata of an inherited dependency property by calling the OverrideMetadata method. Overriding the metadata lets you modify characteristics of the inherited dependency property to match subclass-specific requirements.

Background

A class that defines a dependency property can specify its characteristics in PropertyMetadata or one of its derived types, such as FrameworkPropertyMetadata. One of those characteristics is the default value of a dependency property. Many classes that define dependency properties, specify property metadata during dependency property registration. When metadata isn't specified during registration, the WPF property system assigns a PropertyMetadata object with default values. Derived classes that inherit dependency properties through class inheritance have the option to override the original metadata of any dependency property. In this way, derived classes can selectively modify dependency property characteristics to meet class requirements. When calling OverrideMetadata(Type, PropertyMetadata), a derived class specifies its own type as the first parameter, and a metadata instance as the second parameter.

A derived class that overrides metadata on a dependency property must do so before the property is placed in use by the property system. A dependency property is placed in use when any instance of the class that registers the property is instantiated. To help meet this requirement, the derived class should call OverrideMetadata within its static constructor. Overriding the metadata of a dependency property after its owner type is instantiated won't raise exceptions, but will result in inconsistent behaviors in the property system. Also, a derived type can't override the metadata of a dependency property more than once, and attempts to do so will raise an exception.

Example

In the following example, the derived class TropicalAquarium overrides the metadata of a dependency property inherited from the base class Aquarium. The metadata type is FrameworkPropertyMetadata, which supports UI-related WPF framework characteristics such as AffectsRender. The derived class doesn't override the inherited AffectsRender flag, but it does update the default value of AquariumGraphic on derived class instances.

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, owner type, and property metadata.
    public static readonly DependencyProperty AquariumGraphicProperty =
        DependencyProperty.Register(
          name: "AquariumGraphic",
          propertyType: typeof(Uri),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata(
              defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
              flags: FrameworkPropertyMetadataOptions.AffectsRender)
        );

    // Declare a read-write CLR wrapper with get/set accessors.
    public Uri AquariumGraphic
    {
        get => (Uri)GetValue(AquariumGraphicProperty);
        set => SetValue(AquariumGraphicProperty, value);
    }
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, owner type, and property metadata.
    Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
        DependencyProperty.Register(
            name:="AquariumGraphic",
            propertyType:=GetType(Uri),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a read-write CLR wrapper with get/set accessors.
    Public Property AquariumGraphic As Uri
        Get
            Return CType(GetValue(AquariumGraphicProperty), Uri)
        End Get
        Set
            SetValue(AquariumGraphicProperty, Value)
        End Set
    End Property

End Class
public class TropicalAquarium : Aquarium
{
    // Static constructor.
    static TropicalAquarium()
    {
        // Create a new metadata instance with a modified default value.
        FrameworkPropertyMetadata newPropertyMetadata = new(
            defaultValue: new Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"));

        // Call OverrideMetadata on the dependency property identifier.
        // Pass in the type for which the new metadata will be applied
        // and the new metadata instance.
        AquariumGraphicProperty.OverrideMetadata(
            forType: typeof(TropicalAquarium),
            typeMetadata: newPropertyMetadata);
    }
}
Public Class TropicalAquarium
    Inherits Aquarium

    ' Static constructor.
    Shared Sub New()
        ' Create a new metadata instance with a modified default value.
        Dim newPropertyMetadata As New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"))

        ' Call OverrideMetadata on the dependency property identifier.
        ' Pass in the type for which the new metadata will be applied
        ' and the new metadata instance.
        AquariumGraphicProperty.OverrideMetadata(
            forType:=GetType(TropicalAquarium),
            typeMetadata:=newPropertyMetadata)
    End Sub

End Class

See also