属性值继承Property Value Inheritance

属性值继承是 Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 属性系统的一项功能。Property value inheritance is a feature of the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) property system. 属性值继承使元素树中的子元素可以从父元素获取特定属性的值,并继承该值,就如同它是在最近的父元素中任意位置设置的一样。Property value inheritance enables child elements in a tree of elements to obtain the value of a particular property from parent elements, inheriting that value as it was set anywhere in the nearest parent element. 父元素可能也已通过属性值继承获得了其值,因此系统有可能一直递归到页面根。The parent element might also have obtained its value through property value inheritance, so the system potentially recurses all the way to the page root. 属性值继承不是默认属性系统行为;属性必须用特定的元数据设置来建立,以便使该属性对子元素启动属性值继承。Property value inheritance is not the default property system behavior; a property must be established with a particular metadata setting in order to cause that property to initiate property value inheritance on child elements.

属性值继承是内含继承Property Value Inheritance Is Containment Inheritance

此处作为术语的“继承”与类型和常规的面向对象的编程中提到的继承并非完全相同的概念,后者指派生类从其基类继承成员定义。"Inheritance" as a term here is not quite the same concept as inheritance in the context of types and general object-oriented programming, where derived classes inherit member definitions from their base classes. 继承的这一含义在 WPFWPF 中也适用:当在代码中用作元素且公开为成员时,各基类中定义的属性将公开为 XAMLXAML 派生类的特性。That meaning of inheritance is also active in WPFWPF: properties defined in various base classes are exposed as attributes for derived XAMLXAML classes when used as elements, and exposed as members for code. 属性值继承则是关于属性值如何基于元素树中的父子关系从一个元素继承到另一个元素。Property value inheritance is particularly about how property values can inherit from one element to another on the basis of the parent-child relationships within a tree of elements. 如果在 XAMLXAML 标记中定义应用程序时将元素嵌套在其他元素中,则该元素树在此种情况下最直接可见。That tree of elements is most directly visible when nesting elements inside other elements as you define applications in XAMLXAML markup. 还可以通过向其他对象的指定集合中添加对象来以编程方式创建对象树,在运行时,属性值继承在完成树中以相同方式工作。Trees of objects can also be created programmatically by adding objects to designated collections of other objects, and property value inheritance works the same way in the finished tree at run time.

属性值继承的实际应用Practical Applications of Property Value Inheritance

WPFWPF Api 包括多个启用了属性继承的属性。The WPFWPF APIs include several properties that have property inheritance enabled. 通常,使用这些属性的情况是当涉及到一个属性,每页可以仅对该属性设置一次,但是该属性还是某个基元素类的成员,因此还存在于大多数子元素中。Typically, the scenario for these is that they involve a property where it is appropriate that the property be set only once per page, but where that property is also a member of one of the base element classes and thus would also exist on most of the child elements. 例如, FlowDirection属性控制应在页面上显示和排列流动内容的方向。For example, the FlowDirection property controls which direction flowed content should be presented and arranged on the page. 通常做法是在所有子元素中以一致的方式处理文本流概念。Typically, you want the text flow concept to be handled consistently throughout all child elements. 如果用户或环境操作因某种原因在元素树的某一层重置了流方向,则流方向通常会在整个树中重置。If flow direction were for some reason reset in some level of the element tree by user or environment action, it should typically be reset throughout. FlowDirection当属性进行继承时, 只需在元素树中的级别上设置或重置此值一次, 该级别包含应用程序中每个页面的显示需求。When the FlowDirection property is made to inherit, the value need only be set or reset once at the level in the element tree that encompasses the presentation needs of each page in the application. 即使是最初的默认值也将按照这种方式继承。Even the initial default value will inherit in this way. 在需有意混用流方向的极罕见情况下,属性值继承模型也仍允许个别元素重置该值。The property value inheritance model still enables individual elements to reset the value for the rare cases where having a mix of flow directions is intentional.

使自定义属性可继承Making a Custom Property Inheritable

通过更改自定义属性的元数据,还可以使自己的自定义属性可继承。By changing a custom property's metadata, you can also make your own custom properties inheritable. 但是,请注意,将属性指定为可继承需要考虑到性能问题。Note, however, that designating a property as inheritable does have some performance considerations. 如果该属性没有已建立的本地值或通过样式、模板或数据绑定获取的值,则可继承的属性会将赋予它的属性值提供给逻辑树中的所有子元素。In cases where that property does not have an established local value, or a value obtained through styles, templates, or data binding, an inheritable property provides its assigned property values to all child elements in the logical tree.

为了让属性参与值继承,请按照注册附加属性中所述创建自定义附加属性。To make a property participate in value inheritance, create a custom attached property, as described in Register an Attached Property. 将属性注册为元数据FrameworkPropertyMetadata(), 并在该元数据的选项设置中指定 "继承" 选项。Register the property with metadata (FrameworkPropertyMetadata) and specify the "Inherits" option in the options settings within that metadata. 同时确保该属性已建立了默认值,因为该值现将继承。Also make sure that the property has an established default value, because that value will now inherit. 尽管已将该属性注册为附加属性,可能还需像对“非附加”依赖项属性一样,为所有者类型上的 get/set 访问创建属性“包装”。Although you registered the property as attached, you might also want to create a property "wrapper" for get/set access on the owner type, just as you would for an "nonattached" dependency property. 完成此操作后, 可以通过使用所有者类型或派生类型上的直接属性包装器设置可继承属性, 也可以通过在任何DependencyObject上使用附加属性语法来设置该属性。After doing so, the inheritable property can either be set by using the direct property wrapper on the owner type or derived types, or it can be set by using the attached property syntax on any DependencyObject.

附加属性在概念上类似于全局属性;您可以检查任何DependencyObject值并获得有效结果。Attached properties are conceptually similar to global properties; you can check for the value on any DependencyObject and get a valid result. 附加属性的典型方案是在子元素上设置属性值, 如果相关属性是一个附加属性, 而该属性始终作为每个元素DependencyObject上的附加属性隐式显示,则该方案更有效。)。The typical scenario for attached properties is to set property values on child elements, and that scenario is more effective if the property in question is an attached property that is always implicitly present as an attached property on each element (DependencyObject) in the tree.

备注

尽管属性值继承看起来对非附加依赖项属性有效,但通过运行时树中特定元素边界的非附加属性的继承行为并未定义。Although property value inheritance might appear to work for nonattached dependency properties, the inheritance behavior for a nonattached property through certain element boundaries in the run-time tree is undefined. 始终使用RegisterAttached来注册在元数据中Inherits指定的属性。Always use RegisterAttached to register properties where you specify Inherits in the metadata.

跨树边界继承属性值Inheriting Property Values Across Tree Boundaries

属性继承通过遍历元素树来工作。Property inheritance works by traversing a tree of elements. 此树通常与逻辑树并行。This tree is often parallel to the logical tree. 但是, 无论何时在定义元素树的标记中包括 WPF 核心级别对象 (例如Brush), 都已创建不连续的逻辑树。However, whenever you include a WPF core-level object in the markup that defines an element tree, such as a Brush, you have created a discontinuous logical tree. True 逻辑树在概念上并不贯穿Brush, 因为逻辑树是 WPF 框架级别的概念。A true logical tree does not conceptually extend through the Brush, because the logical tree is a WPF framework-level concept. 使用的LogicalTreeHelper方法时, 可以看到此结果反映在结果中。You can see this reflected in the results when using the methods of LogicalTreeHelper. 但是, 只要可继承属性注册为附加属性, 且没有有意的继承阻止边界 (如Frame,则属性值继承就可以在逻辑树中弥补这种间隔,但仍可通过传递继承的值)。)。However, property value inheritance can bridge this gap in the logical tree and can still pass inherited values through, so long as the inheritable property was registered as an attached property and no deliberate inheritance-blocking boundary (such as a Frame) is encountered.

请参阅See also