Framework Property Metadata
Framework property metadata options are reported for the properties of object elements considered to be at the WPF framework level in the Windows Presentation Foundation (WPF) architecture. In general the WPF framework-level designation entails that features such as rendering, data binding, and property system refinements are handled by the WPF presentation APIs and executables. Framework property metadata is queried by these systems to determine feature-specific characteristics of particular element properties.
This topic contains the following sections.
- Prerequisites
- What Is Communicated by Framework Property Metadata
- Reading FrameworkPropertyMetadata
- Specifying Metadata
- Framework Property Metadata Merge Behavior
- Related Topics
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing dependency properties on Windows Presentation Foundation (WPF) classes, and have read the Dependency Properties Overview. You should also have read Dependency Property Metadata.
What Is Communicated by Framework Property Metadata
Framework property metadata can be divided into the following categories:
Reporting layout properties that affect an element (AffectsArrange, AffectsMeasure, AffectsRender). You might set these flags in metadata if the property affects those respective aspects, and you are also implementing the MeasureOverride / ArrangeOverride methods in your class to supply specific rendering behavior and information to the layout system. Typically, such an implementation would check for property invalidations in dependency properties where any of these layout properties were true in the property metadata, and only those invalidations would necessitate requesting a new layout pass.
Reporting layout properties that affect the parent element of an element (AffectsParentArrange, AffectsParentMeasure). Some examples where these flags are set by default are FixedPage.Left and Paragraph.KeepWithNext.
Inherits. By default, dependency properties do not inherit values. OverridesInheritanceBehavior allows the pathway of inheritance to also travel into a visual tree, which is necessary for some control compositing scenarios.
Note
The term "inherits" in the context of property values means something specific for dependency properties; it means that child elements can inherit the actual dependency property value from parent elements because of a WPF framework-level capability of the WPF property system. It has nothing to do directly with managed code type and members inheritance through derived types. For details, see Property Value Inheritance.
Reporting data binding characteristics (IsNotDataBindable, BindsTwoWayByDefault). By default, dependency properties in the framework support data binding, with a one-way binding behavior. You might disable data binding if there were no scenario for it whatsoever (because they are intended to be flexible and extensible, there aren't many examples of such properties in the default WPF APIs). You might set binding to have a two-way default for properties that tie together a control's behaviors amongst its component pieces (IsSubmenuOpen is an example) or where two-way binding is the common and expected scenario for users (Text is an example). Changing the data binding–related metadata only influences the default; on a per-binding basis that default can always be changed. For details on the binding modes and binding in general, see Data Binding Overview.
Reporting whether properties should be journaled by applications or services that support journaling (Journal). For general elements, journaling is not enabled by default, but it is selectively enabled for certain user input controls. This property is intended to be read by journaling services including the WPF implementation of journaling, and is typically set on user controls such as user selections within lists that should be persisted across navigation steps. For information about the journal, see Navigation Overview.
Reading FrameworkPropertyMetadata
Each of the properties linked above are the specific properties that the FrameworkPropertyMetadata adds to its immediate base class UIPropertyMetadata. Each of these properties will be false by default. A metadata request for a property where knowing the value of these properties is important should attempt to cast the returned metadata to FrameworkPropertyMetadata, and then check the values of the individual properties as needed.
Specifying Metadata
When you create a new metadata instance for purposes of applying metadata to a new dependency property registration, you have the choice of which metadata class to use: the base PropertyMetadata or some derived class such as FrameworkPropertyMetadata. In general, you should use FrameworkPropertyMetadata, particularly if your property has any interaction with property system and WPF functions such as layout and data binding. Another option for more sophisticated scenarios is to derive from FrameworkPropertyMetadata to create your own metadata reporting class with extra information carried in its members. Or you might use PropertyMetadata or UIPropertyMetadata to communicate the degree of support for features of your implementation.
For existing properties (AddOwner or OverrideMetadata call), you should always override with the metadata type used by the original registration.
If you are creating a FrameworkPropertyMetadata instance, there are two ways to populate that metadata with values for the specific properties that communicate the framework property characteristics:
Use the FrameworkPropertyMetadata constructor signature that allows a flags parameter. This parameter should be filled with all desired combined values of the FrameworkPropertyMetadataOptions enumeration flags.
Use one of the signatures without a flags parameter, and then set each reporting Boolean property on FrameworkPropertyMetadata to true for each desired characteristic change. If you do this, you must set these properties before any elements with this dependency property are constructed; the Boolean properties are read-write in order to allow this behavior of avoiding the flags parameter and still populate the metadata, but the metadata must become effectively sealed before property use. Thus, attempting to set the properties after metadata is requested will be an invalid operation.
Framework Property Metadata Merge Behavior
When you override framework property metadata, the different metadata characteristics are either merged or replaced.
PropertyChangedCallback is merged. If you add a new PropertyChangedCallback, that callback is stored in the metadata. If you do not specify a PropertyChangedCallback in the override, the value of PropertyChangedCallback is promoted as a reference from the nearest ancestor that specified it in metadata.
The actual property system behavior for PropertyChangedCallback is that implementations for all metadata owners in the hierarchy are retained and added to a table, with order of execution by the property system being that the callbacks of the most deeply derived class are invoked first. Inherited callbacks run only once, counting as being owned by the class that placed them in metadata.
DefaultValue is replaced. If you do not specify a PropertyChangedCallback in the override, the value of DefaultValue comes from the nearest ancestor that specified it in metadata.
CoerceValueCallback implementations are replaced. If you add a new CoerceValueCallback, that callback is stored in the metadata. If you do not specify a CoerceValueCallback in the override, the value of CoerceValueCallback is promoted as a reference from the nearest ancestor that specified it in metadata.
The property system behavior is that only the CoerceValueCallback in the immediate metadata is invoked. No references to other CoerceValueCallback implementations in the hierarchy are retained.
The flags of FrameworkPropertyMetadataOptions enumeration are combined as a bitwise OR operation. If you specify FrameworkPropertyMetadataOptions, the original options are not overwritten. To change an option, set the corresponding property on FrameworkPropertyMetadata. For example, if the original FrameworkPropertyMetadata object sets the FrameworkPropertyMetadataOptions.NotDataBindable flag, you can change that by setting FrameworkPropertyMetadata.IsNotDataBindable to false.
This behavior is implemented by Merge, and can be overridden on derived metadata classes.