Redigera

Dela via


Framework property metadata (WPF .NET)

You can set framework property metadata options for dependency properties at the Windows Presentation Foundation (WPF) framework level. The WPF framework level designation applies when WPF presentation APIs and executables handle rendering and data binding. Presentation APIs and executables query the FrameworkPropertyMetadata of a dependency property.

Prerequisites

The article assumes a basic knowledge of dependency properties, and that you've read Dependency properties overview. To follow the examples in this article, it helps if you're familiar with Extensible Application Markup Language (XAML) and know how to write WPF applications.

Framework property metadata categories

FrameworkPropertyMetadata falls into these categories:

  • Metadata that affects the layout of an element, specifically the AffectsArrange, AffectsMeasure, and AffectsRender metadata flags. You might set those flags if your dependency property implementation affects a visual aspect and you're implementing MeasureOverride or ArrangeOverride in your class. The MeasureOverride and ArrangeOverride methods provide implementation-specific behavior and rendering information to the layout system. When AffectsArrange, AffectsMeasure, or AffectsRender are set to true in the metadata of a dependency property and its effective value changes, the WPF property system will initiate a request to invalidate the element's visuals to trigger a redraw.

  • Metadata that affects the layout of the parent element of an element, specifically the AffectsParentArrange and AffectsParentMeasure metadata flags. Examples of WPF dependency properties that set these flags are FixedPage.Left and Paragraph.KeepWithNext.

  • Property value inheritance metadata, specifically the Inherits and OverridesInheritanceBehavior metadata flags. By default, dependency properties don't inherit values. OverridesInheritanceBehavior allows the pathway of inheritance to also travel into a visual tree, which is necessary for some control compositing scenarios. For more information, see Property value inheritance.

    Note

    The term "inherits" in the context of property values is specific to dependency properties, and doesn't directly relate to managed code types and member inheritance through derived types. In the context of dependency properties, it means that child elements can inherit dependency property values from parent elements.

  • Data binding metadata, specifically the BindsTwoWayByDefault and IsNotDataBindable metadata flags. By default, dependency properties in the WPF framework support one-way binding. Consider setting two-way binding as the default for properties that report state and are modifiable by user action, for example IsSelected. Also, consider setting two-way binding as the default when users of a control expect a property to implement it, for example TextBox.Text. BindsTwoWayByDefault only affects the default binding mode. To edit the data flow direction of a binding, set Binding.Mode. You can use IsNotDataBindable to disable data binding when there's no use case for it. For more information on data bindings, see Data binding overview.

  • Journaling metadata, specifically the Journal metadata flag. The default value of the Journal flag is only true for a some dependency properties, such as SelectedIndex. User input controls should set the Journal flag for properties whose values hold user selections that need to be stored. The Journal flag is read by applications or services that support journaling, including WPF journaling services. For information on storing navigation steps, see Navigation overview.

FrameworkPropertyMetadata derives directly from UIPropertyMetadata, and implements the flags discussed here. Unless specifically set, FrameworkPropertyMetadata flags have a default value of false.

Reading FrameworkPropertyMetadata

To retrieve metadata for a dependency property, call GetMetadata on the DependencyProperty identifier. The GetMetadata call returns a PropertyMetadata object. If you need to query framework metadata values cast PropertyMetadata to FrameworkPropertyMetadata.

Specifying FrameworkPropertyMetadata

When you register a dependency property, you have the option to create and assign metadata to it. The metadata object that you assign can be PropertyMetadata or one of its derived classes, like FrameworkPropertyMetadata. Choose FrameworkPropertyMetadata for dependency properties that rely on WPF presentation APIs and executables for rendering and data binding. A more advanced option is to derive from FrameworkPropertyMetadata to create a custom metadata reporting class with more flags. Or, you might use UIPropertyMetadata for non-framework properties that affect UI rendering.

Although metadata options are typically set during registration of a new dependency property, you can respecify them in OverrideMetadata or AddOwner calls. When overriding metadata, always override with the same metadata type that was used during property registration.

The property characteristics that are exposed by FrameworkPropertyMetadata are sometimes referred to as flags. If you're creating a FrameworkPropertyMetadata instance, there are two ways to populate flag values:

  1. Set the flags on an instance of the FrameworkPropertyMetadataOptions enumeration type. FrameworkPropertyMetadataOptions lets you specify metadata flags in bitwise OR combination. Then, instantiate FrameworkPropertyMetadata using a constructor that has a FrameworkPropertyMetadataOptions parameter, and pass in your FrameworkPropertyMetadataOptions instance. To change metadata flags after passing FrameworkPropertyMetadataOptions into the FrameworkPropertyMetadata constructor, change the corresponding property on the new FrameworkPropertyMetadata instance. For example, if you set the FrameworkPropertyMetadataOptions.NotDataBindable flag, you can undo that by setting FrameworkPropertyMetadata.IsNotDataBindable to false.

  2. Instantiate FrameworkPropertyMetadata using a constructor that doesn't have a FrameworkPropertyMetadataOptions parameter, and then set the applicable Boolean flags on FrameworkPropertyMetadata. Set flag values before associating your FrameworkPropertyMetadata instance with a dependency property, otherwise you'll get an InvalidOperationException.

Metadata override behavior

When you override framework property metadata, changed metadata values either replace or are merged with the original values:

  • For a PropertyChangedCallback, the default merge logic retains previous PropertyChangedCallback values in a table, and all are invoked on a property change. The callback order is determined by class depth, where a callback registered by the base class in the hierarchy would run first. Inherited callbacks run only once, and are owned by the class that added them into metadata.

  • For a DefaultValue, the new value will replace the existing default value. If you don't specify a DefaultValue in the override metadata and if the existing FrameworkPropertyMetadata has the Inherits flag set, then the default value comes from the nearest ancestor that specified DefaultValue in metadata.

  • For a CoerceValueCallback, the new value will replace an existing CoerceValueCallback value. If you don't specify a CoerceValueCallback in the override metadata, the value comes from the nearest ancestor in the inheritance chain that specified a CoerceValueCallback.

  • For FrameworkPropertyMetadata non-inherited flags, you can override the default false value with a true value. However, you can only override a true value with a false value for Inherits, Journal, OverridesInheritanceBehavior, and SubPropertiesDoNotAffectRender.

Note

The default merge logic is implemented by the Merge method. You can specify custom merge logic in a derived class that inherits a dependency property, by overriding Merge in that class.

See also