XAML 加载和依赖属性

XAML 处理器的当前 WPF 实现固有地知道依赖属性。 WPF XAML 处理器在加载二进制 XAML 和处理作为依赖属性的特性时对依赖属性使用属性系统方法。 这会有效地跳过属性包装器。 实现自定义依赖属性时,必须要考虑到此行为,并应避免在属性包装器中放入除属性系统方法 GetValueSetValue 以外的任何其他代码。

先决条件

本主题假定你已从使用者和创作者角度了解依赖属性,并已阅读依赖属性概述自定义依赖属性。 你应也已阅读 WPF 中的 XAMLXAML 语法详述

WPF XAML 加载程序实现和性能

出于实现原因,相较于使用属性包装器和资源库,将属性标识为依赖属性并通过访问属性系统 SetValue 方法对其进行设置的计算成本较低。 这是因为 XAML 处理器必须仅通过了解由标记结构和多种字符串所指示的类型和成员关系来推断支持代码的整个对象模型。

虽然此类型可通过结合 xmlns 和程序集属性来查询,但标识成员、确定支持设置为属性的项和解析属性值支持的类型则需要使用 PropertyInfo 的扩展反射。 因为给定类型的依赖属性通过属性系统可作为存储表进行访问,因此 XAML 处理器的 WPF 实现使用此表,并推断出可通过使用依赖属性标识符 ABCProperty 在所含 DependencyObject 派生类型上调用 SetValue 来更高效设置任何给定属性 ABC

自定义依赖属性的影响

由于进行属性设置的 XAML 处理器行为的当前 WPF 实现会完全跳过包装器,因此对于自定义依赖属性不应将任何其他逻辑放入包装器的设置定义中。 如果将此类逻辑放入设置定义,则在 XAML 而不是代码中设置属性时不会执行逻辑。

同样,从 XAML 处理获取属性值的 XAML 处理器的其他方面也会使用 GetValue 而不是使用包装器。 因此,在超出 GetValue 调用的 get 定义中,还应避免任何其他实现。

如下示例是包装器的推荐依赖属性定义,其中属性标识符存储为 publicstaticreadonly 字段,getset 定义不包含除定义依赖属性支持所需属性系统方法外的任何代码。


public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender,
      new PropertyChangedCallback(OnUriChanged)
  )
);
public Uri AquariumGraphic
{
  get { return (Uri)GetValue(AquariumGraphicProperty); }
  set { SetValue(AquariumGraphicProperty, value); }
}

Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = DependencyProperty.Register("AquariumGraphic", GetType(Uri), GetType(AquariumObject), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf OnUriChanged)))
Public Property AquariumGraphic() As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set(ByVal value As Uri)
        SetValue(AquariumGraphicProperty, value)
    End Set
End Property

另请参阅