Carga de XAML y propiedades de dependencia

La implementación actual de WPF de su procesador de XAML es intrínsecamente compatible con la propiedad de dependencia. El procesador de XAML de WPF usa métodos del sistema de propiedades para las propiedades de dependencia al cargar el XAML binario y al procesar atributos que son propiedades de dependencia. En la práctica esto supone la omisión de los contenedores de propiedad. Al implementar propiedades de dependencia personalizadas, debe tener en cuenta este comportamiento y evitar incluir en el contenedor de propiedad ningún código que no sean los métodos del sistema de propiedades GetValue y SetValue.

Requisitos previos

En este tema se presupone que comprende las propiedades de dependencia como consumidor y como autor, y que ha leído Información general sobre las propiedades de dependencia y Propiedades de dependencia personalizadas. También es conveniente haber leído XAML en WPF y Detalles de la sintaxis XAML.

Implementación de cargador de XAML de WPF y rendimiento

Por motivos de implementación, resulta menos costoso desde el punto de vista de la informática identificar una propiedad como de dependencia y tener acceso al método SetValue del sistema de propiedades para establecerla, en lugar de usar el contenedor de propiedad y su establecedor. Esto se debe a que un procesador XAML debe deducir el modelo de objetos completo del código de respaldo basándose únicamente en las relaciones entre los miembros y los tipos que se indican en la estructura del marcado y en diversas cadenas.

El tipo se busca mediante una combinación de xmlns y atributos de ensamblado, pero para identificar los miembros, determinar cuáles admiten que se los establezca como atributos, y resolver qué tipos admiten los valores de propiedad, se requeriría realizar una extensa reflexión mediante PropertyInfo. Dado que las propiedades de dependencia de un tipo determinado son accesibles como una tabla de almacenamiento a través del sistema de propiedades, la implementación en WPF del procesador XAML usa esta tabla y deduce que cualquier propiedad ABC determinada se puede establecer de un modo más eficaz llamando al método SetValue del tipo derivado contenedor DependencyObject, para lo que se usa el identificador de propiedad de dependencia ABCProperty.

Implicaciones para las propiedades de dependencia personalizadas

Dado que la implementación actual en WPF del comportamiento del procesador XAML para establecer propiedades omite completamente los contenedores, no se debe incluir ninguna lógica adicional en las definiciones de conjuntos del contenedor para la propiedad de dependencia personalizada. Si incluye lógica de este tipo en la definición de conjuntos, dicha lógica no se ejecutará cuando la propiedad se establezca en XAML en lugar de en el código.

De igual forma, otros aspectos del procesador XAML que obtienen valores de propiedades del procesamiento XAML también usan GetValue en lugar del contenedor. Por consiguiente, también se debe evitar cualquier implementación adicional en la definición get que no sea la llamada a GetValue.

El ejemplo siguiente es una definición de propiedad de dependencia recomendada con contenedores, donde el identificador de propiedad está almacenado como un campo publicstaticreadonly y las definiciones de get y set no contienen ningún código excepto los métodos del sistema de propiedades necesarios que definen la lógica de respaldo de las propiedades de dependencia.


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

Vea también