Metadatos de propiedades de dependencia (WPF .NET)

El sistema de propiedades de Windows Presentation Foundation de (WPF) incluye un sistema de informes de metadatos de propiedades de dependencia. La información disponible a través del sistema de informes de metadatos supera lo que está disponible a través de la reflexión o las características generales de Common Language Runtime (CLR). Al registrar una propiedad de dependencia, tiene la opción de crear metadatos y asignárselos. Si deriva de una clase que define una propiedad de dependencia, puede invalidar los metadatos de la propiedad de dependencia heredada. Y si agrega la clase como propietario de una propiedad de dependencia, puede invalidar los metadatos de la propiedad de dependencia heredada.

Importante

La documentación de la Guía de escritorio para .NET 6 y .NET 5 (incluido .NET Core 3.1) está en elaboración.

Requisitos previos

En el artículo se da por supuesto que tiene un conocimiento básico de las propiedades de dependencia y que ha leído Información general sobre las propiedades de dependencia. Para seguir los ejemplos de este artículo, resultará útil que esté familiarizado con el Lenguaje de marcado de aplicación extensible (XAML) y sepa cómo escribir aplicaciones WPF.

Cómo se usan los metadatos

Puede consultar los metadatos de la propiedad de dependencia para examinar las características de una propiedad de dependencia. Cuando el sistema de propiedades procesa una propiedad de dependencia, accede a sus metadatos. El objeto de metadatos de una propiedad de dependencia contiene los siguientes tipos de información:

  • Valor predeterminado de la propiedad de dependencia, que el sistema de propiedades establece cuando no se aplica ningún otro valor, como un valor local, de estilo o de herencia. Para obtener más información sobre la prioridad de los valores durante la asignación en tiempo de ejecución de los valores de propiedad de dependencia, consulte Prioridad de los valores de propiedad de dependencia.

  • Referencias a devoluciones de llamada de valor de coerción y devoluciones de llamada de cambio de propiedad en el tipo de propietario. Solo puede obtener referencias a devoluciones de llamada que tengan un modificador de acceso public o que estén dentro del ámbito de acceso permitido. Para obtener más información sobre las devoluciones de llamada de propiedad de dependencia, consulte Devoluciones de llamada de propiedad de dependencia y validación.

  • Características de la propiedad de dependencia de nivel de marco de WPF (si la propiedad de dependencia es una propiedad de marco de WPF). Los procesos de WPF, como el motor de diseño de marco y la lógica de herencia de propiedades, consultan los metadatos de nivel de marco de WPF. Para obtener más información, consulte Metadatos de las propiedades de marco.

API de metadatos

La clase PropertyMetadata almacena la mayoría de los metadatos utilizados por el sistema de propiedades. Las instancias de metadatos se pueden crear y asignar mediante:

  • Tipos que registran propiedades de dependencia con el sistema de propiedades.

  • Tipos que heredan de una clase que define una propiedad de dependencia.

  • Tipos que se agregan a sí mismos como propietario de una propiedad de dependencia.

Si un tipo registra una propiedad de dependencia sin especificar metadatos, el sistema de propiedades asigna un objeto PropertyMetadata con valores predeterminados para ese tipo a la propiedad de dependencia.

Para recuperar los metadatos de una propiedad de dependencia, llame a una de las sobrecargas GetMetadata del identificador DependencyProperty. Los metadatos se devuelven como un objeto PropertyMetadata.

Existen clases de metadatos más específicas, derivadas de PropertyMetadata, para diferentes áreas arquitectónicas. Por ejemplo, UIPropertyMetadata admite informes de animación y FrameworkPropertyMetadata admite propiedades de marco de WPF. Las propiedades de dependencia también se pueden registrar con las clases derivadas de PropertyMetadata. Aunque GetMetadata devuelve un objeto PropertyMetadata, cuando sea aplicable, puede convertir a un tipo derivado para examinar las propiedades específicas del tipo.

Las características de propiedad expuestas por FrameworkPropertyMetadata a veces se conocen como marcas. Al crear una instancia FrameworkPropertyMetadata, tiene la opción de pasar una instancia del tipo de enumeración FrameworkPropertyMetadataOptions al constructorFrameworkPropertyMetadata. FrameworkPropertyMetadataOptions permite especificar marcas de metadatos en combinación bit a bit. El FrameworkPropertyMetadata utiliza FrameworkPropertyMetadataOptions para mantener la longitud de su firma de constructor en un valor razonable. En el registro de propiedades de dependencia, las marcas de metadatos establecidas en FrameworkPropertyMetadataOptions se exponen en FrameworkPropertyMetadata como propiedades Boolean, en lugar de como una combinación bit a bit de marcas, para que las características de metadatos de consulta sean más intuitivas.

¿Invalidar o crear nuevos metadatos?

Cuando se hereda una propiedad de dependencia, se tiene la opción de cambiar las características de la propiedad de dependencia invalidando sus metadatos. Sin embargo, no siempre será posible que pueda realizar el escenario de la propiedad de dependencia invalidando los metadatos y, a veces, será necesario definir una propiedad de dependencia personalizada en la clase con nuevos metadatos. Las propiedades de dependencia personalizadas tienen las mismas funcionalidades que las propiedades de dependencia definidas por los tipos de WPF. Para más información, consulte Propiedades de dependencia personalizadas.

Una característica de una propiedad de dependencia que no se puede invalidar es su tipo de valor. Si una propiedad de dependencia heredada tiene el comportamiento aproximado que necesita, pero el escenario requiere un tipo de valor diferente, considere la posibilidad de implementar una propiedad de dependencia personalizada. Es posible que pueda vincular los valores de propiedad a través de la conversión de tipos u otra implementación en la clase derivada.

Escenarios para invalidar metadatos

Los escenarios de ejemplo para invalidar los metadatos de propiedad de dependencia existentes son:

  • Cambiar el valor predeterminado, que es un escenario común.

  • Cambiar o agregar devoluciones de llamada de cambio de propiedad, lo cual podría ser necesario si una propiedad de dependencia heredada interactúa con otras propiedades de dependencia de forma diferente a como lo hace su implementación base. Una de las características de un modelo de programación que admite, tanto código, como marcado es que los valores de propiedad se pueden establecer en cualquier orden. Este factor puede afectar a la forma en que se implementan las devoluciones de llamada de cambio de propiedad. Para obtener más información, consulte Devoluciones de llamada y validación de las propiedades de dependencia.

  • Cambiar las opciones de metadatos de propiedades del marco de WPF. Normalmente, las opciones de metadatos se establecen durante el registro de una nueva propiedad de dependencia, pero puede volver a especificarlas en llamadas a OverrideMetadata o AddOwner. Para obtener más información sobre cómo invalidar los metadatos de propiedad del marco, consulte Especificar metadatos. Para obtener información sobre cómo establecer opciones de metadatos de propiedad de marco al registrar una propiedad de dependencia, consulte Propiedades de dependencia personalizadas.

Nota:

Dado que las devoluciones de llamada de validación no forman parte de los metadatos, no se pueden cambiar invalidando los metadatos. Para obtener más información, consulte Devoluciones de llamada de validación.

Invalidación de metadatos

Al implementar una nueva propiedad de dependencia, puede establecer sus metadatos mediante sobrecargas del método Register. Si la clase hereda una propiedad de dependencia, puede invalidar los valores de metadatos heredados mediante el método OverrideMetadata. Por ejemplo, puede usar OverrideMetadata para establecer valores específicos del tipo. Para obtener más información y ejemplos de código, consulte Invalidar metadatos para una propiedad de dependencia.

Un ejemplo de una propiedad de dependencia de WPF es Focusable. La clase FrameworkElement registra Focusable. La clase Control deriva de FrameworkElement, hereda la propiedad de dependencia Focusable e invalida los metadatos de propiedad heredados. La invalidación cambia el valor de propiedad predeterminado de false a true, pero conserva otros valores de metadatos heredados.

Puesto que la mayoría de las propiedades de dependencia existentes no son propiedades virtuales, su implementación heredada «ensombrece» el miembro existente. Al invalidar una característica de metadatos, el nuevo valor de metadatos reemplaza el valor original o se combina:

  • Para un DefaultValue, el nuevo valor reemplazará el valor predeterminado existente. Si no especifica un DefaultValue en los metadatos de invalidación, el valor procede del antecesor más cercano que ha especificado DefaultValue en los metadatos.

  • Para un PropertyChangedCallback, la lógica de combinación predeterminada almacena todos los valores de PropertyChangedCallback en una tabla y todos se invocan en un cambio de propiedad. El orden de devolución de llamada viene determinado por la profundidad de clase, donde una devolución de llamada registrada por la clase base en la jerarquía se ejecutaría primero.

  • Para un CoerceValueCallback, el nuevo valor reemplazará el valor CoerceValueCallback existente. Si no especifica un CoerceValueCallback en los metadatos de invalidación, el valor procede del antecesor más cercano que ha especificado CoerceValueCallback en los metadatos.

Nota:

El método Merge implementa la lógica de combinación predeterminada. Puede especificar la lógica de combinación personalizada en una clase derivada que hereda una propiedad de dependencia invalidando Merge en esa clase.

Agregar una clase como propietario

Para «heredar» una propiedad de dependencia registrada en una jerarquía de clases diferente, use el método AddOwner. Este método se usa normalmente cuando la clase de agregación no se deriva del tipo que ha registrado la propiedad de dependencia. En la llamada AddOwner la clase de agregación puede crear y asignar metadatos específicos del tipo para la propiedad de dependencia heredada. Para ser un participante completo en el sistema de propiedades, mediante código y marcado, la clase de agregación debe implementar estos miembros públicos:

  • Un campo identificador de propiedad de dependencia. El valor del identificador de propiedad de dependencia es el valor devuelto de la llamada AddOwner. Este campo debe ser un campo public static readonly de tipo DependencyProperty.

  • Un contenedor CLR que implementa get y set descriptores de acceso. Mediante el uso de un contenedor de propiedades, los consumidores de propiedades de dependencia pueden obtener o establecer valores de propiedad de dependencia, como lo harían con cualquier otra propiedad CLR. Los descriptores de acceso get y set interactúan con el sistema de propiedades subyacente a través de llamadas DependencyObject.GetValue y DependencyObject.SetValue, pasando el identificador de propiedad de dependencia como parámetro. Implemente el contenedor de la misma manera que lo haría al registrar una propiedad de dependencia personalizada. Para obtener más información, consulte Propiedades de dependencia personalizadas

Una clase que llama a AddOwner tiene los mismos requisitos para exponer el modelo de objetos de la propiedad de dependencia heredada que una clase que define una nueva propiedad de dependencia personalizada. Para obtener más información, consulte Agregar un tipo de propietario para una propiedad de dependencia.

Metadatos de las propiedades adjuntas

En WPF la mayoría de las propiedades adjuntas relacionadas con la interfaz de usuario en los tipos de WPF se implementan como propiedades de dependencia. Las propiedades adjuntas implementadas como propiedades de dependencia admiten conceptos de propiedad de dependencia, como metadatos que las clases derivadas pueden invalidar. Los metadatos de una propiedad adjunta no suelen ser distintos de los de una propiedad de dependencia. Puede invalidar el valor predeterminado, las devoluciones de llamada de cambio de propiedad y las propiedades del marco de WPF para la propiedad adjunta heredada en instancias de la clase de invalidación. Para obtener más información, consulte Metadatos de propiedades adjuntas

Nota:

Use siempre RegisterAttached para registrar las propiedades donde especifique Inherits en los metadatos. Aunque puede parecer que la herencia de valores de propiedad funciona para las propiedades de dependencia no adjuntas, el comportamiento de herencia de valores de una propiedad no adjunta a través de determinadas divisiones de objetos en el árbol en tiempo de ejecución no está definido. La propiedad Inherits no es relevante para las propiedades no adjuntas. Para obtener más información, consulte RegisterAttached(String, Type, Type, PropertyMetadata) y la sección de comentarios de Inherits.

Agregar una clase como propietario de una propiedad adjunta

Para heredar una propiedad adjunta de otra clase, pero exponerla como una propiedad de dependencia no adjunta en la clase:

  • Llame a AddOwner para agregar la clase como propietario de la propiedad de dependencia adjunta.

  • Asigne el valor devuelto de la llamada AddOwner a un campo public static readonly para usarlo como identificador de propiedad de dependencia.

  • Defina un contenedor CLR, que agrega la propiedad como miembro de clase y admite el uso de propiedades no adjuntas.

Vea también