Metadatos de las propiedades de dependencia
El sistema de propiedades de Windows Presentation Foundation (WPF) incluye un sistema de informe de metadatos que va más allá de lo que se puede informar de una propiedad mediante reflexión o características generales de common language runtime (CLR). Los metadatos para una propiedad de dependencia pueden asignarse también de forma única mediante la clase que define una propiedad de dependencia, pueden modificarse cuando la propiedad de dependencia se agrega a una clase diferente y pueden ser invalidados específicamente por todas las clases derivadas que hereden la propiedad de dependencia de la clase base de la definición.
Este tema contiene las secciones siguientes.
- Requisitos previos
- Cómo se utilizan los metadatos de propiedades de dependencia
- API de metadatos
- Cuándo invalidar metadatos, cuándo derivar una clase
- Escenarios para modificar metadatos existentes
- Temas relacionados
Requisitos previos
En este tema se asume que entiende las propiedades de dependencia desde la perspectiva de un consumidor de las propiedades de dependencia existentes en las clases de Windows Presentation Foundation (WPF) y que ha leído el tema Información general sobre las propiedades de dependencia. Para seguir los ejemplos de este tema, también debe entender XAML y debe saber escribir aplicaciones de WPF.
Cómo se utilizan los metadatos de propiedades de dependencia
Los metadatos de propiedad de dependencia existen como un objeto que se puede consultar para examinar las características de una propiedad de dependencia. El sistema de propiedades tiene acceso también con frecuencia a estos metadatos cuando procesa cualquier propiedad de dependencia determinada. El objeto de metadatos para una propiedad de dependencia puede contener los tipos siguientes de información:
Valor predeterminado para la propiedad de dependencia, si no se puede determinar ningún otro valor para la propiedad de dependencia por valor local, estilo, herencia, etc. Para ver una explicación en profundidad de cómo los valores predeterminados participan en la prioridad utilizada por el sistema de propiedades al asignar valores para las propiedades de dependencia, vea Prioridad de los valores de propiedades de dependencia.
Referencias a las implementaciones de devolución de llamada que afectan a comportamientos de coerción o notificación de cambios propietario por propietario. Tenga en cuenta que estas devoluciones de llamada se definen a menudo con un nivel de acceso no público, así que en general no es posible obtener las referencias reales de los metadatos a menos que estén dentro el ámbito de acceso permitido. Para obtener más información acerca de las devoluciones de llamada de propiedad, vea Devoluciones de llamada y validación de las propiedades de dependencia.
Si la propiedad de dependencia en cuestión se considera una propiedad del nivel de marco de trabajo de WPF, los metadatos pueden contener características de propiedad del nivel de marco de trabajo de WPF, que proporcionan información e indican el estado de servicios tales como el motor de diseño del nivel de marco de trabajo de WPF y la lógica de herencia de propiedad. Para obtener más información sobre este aspecto de los metadatos de propiedad de dependencia, vea Metadatos de las propiedades de marco de trabajo.
API de metadatos
El tipo que informa de la mayor parte de la información de los metadatos utilizados por el sistema de propiedad es la clase PropertyMetadata. Las instancias de metadatos se especifican opcionalmente cuando se registran propiedades de dependencia con el sistema de propiedades y pueden especificarse de nuevo para tipos adicionales que se agregan a sí mismos como propietarios o invalidan los metadatos que heredan de la definición de propiedad de dependencia de la clase base. (Para los casos donde un registro de propiedad no especifica metadatos, se crea un objeto PropertyMetadata predeterminado con valores predeterminados para esa clase.) Los metadatos registrados se devuelven como PropertyMetadata al llamar a las diversas sobrecargas de GetMetadata que obtienen metadatos de una propiedad de dependencia de una instancia de DependencyObject.
Entonces se deriva la clase PropertyMetadata para proporcionar metadatos más concretos para divisiones arquitectónicas tales como las clases de nivel de marco de trabajo de WPF. UIPropertyMetadata agrega informe de animación y FrameworkPropertyMetadata proporciona las propiedades de nivel de marco de trabajo de WPF mencionadas en la sección anterior. Cuando se registra propiedades de dependencia, se puede registrarlas con estas clases derivadas de PropertyMetadata. Cuando se examina los metadatos, el tipo PropertyMetadata base se puede convertir en las clases derivadas para poder examinar las propiedades más concretas.
Nota |
---|
Las características de propiedad que se pueden especificar en FrameworkPropertyMetadata se citan a veces en esta documentación como "marcadores".Al crear nuevas instancias de metadatos para su uso en registros de propiedad de dependencia o invalidaciones de metadatos, debe especificar estos valores mediante la enumeración basada en marcadores FrameworkPropertyMetadataOptions y, a continuación, proporcionar valores de la enumeración posiblemente concatenados al constructor FrameworkPropertyMetadata.Sin embargo, una vez construidas, estas características de opción se exponen dentro de un objeto FrameworkPropertyMetadata como una serie de propiedades booleanas en lugar del valor de enumeración de construcción.Las propiedades booleanas permiten comprobar cada condicional, en lugar de exigir que se aplique una máscara a un valor de enumeración basado en marcas para obtener la información de interés.El constructor utiliza la enumeración FrameworkPropertyMetadataOptions concatenada para mantener la longitud de la firma del constructor dentro de lo razonable, mientras que los metadatos construidos reales exponen las propiedades discretas para hacer que la consulta de los metadatos sea más intuitiva. |
Cuándo invalidar metadatos, cuándo derivar una clase
El sistema de propiedades de WPF ha establecido funciones para modificar algunas características de las propiedades de dependencia sin necesidad de implementarlas de nuevo por completo. Esto se logra construyendo una instancia diferente de los metadatos de propiedad para la propiedad de dependencia tal como existe en un tipo determinado. Tenga en cuenta que la mayoría de las propiedades de dependencia existentes no son propiedades virtuales así que, en rigor, su "reimplementación" en clases heredadas solamente podría lograrse sombreando el miembro existente.
Si el escenario que está intentando habilitar para una propiedad de dependencia en un tipo no se puede lograr modificando características de propiedades de dependencia existentes, puede que sea necesario crear una clase derivada y, a continuación, declarar una propiedad de dependencia personalizada en la clase derivada. Una propiedad de dependencia personalizada se comporta de forma idéntica a las propiedades de dependencia definidas por las APIs de WPF. Para obtener información más detallada sobre las propiedades de dependencia personalizadas, vea Propiedades de dependencia personalizadas.
Una característica notable de una propiedad de dependencia que no se puede invalidar es su tipo de valor. Si está heredando una propiedad de dependencia que tiene el comportamiento aproximado que necesita, pero necesita que tenga un tipo diferente, tendrá que implementar una propiedad de dependencia personalizada y, quizá, vincular las propiedades mediante conversión de tipos u otra implementación en la clase personalizada. Además, no es posible invalidar un objeto ValidateValueCallbackexistente, porque esta devolución de llamada existe en el propio campo de registro y no dentro de sus metadatos.
Escenarios para modificar metadatos existentes
Si está trabajando con metadatos de una propiedad de dependencia existente, un escenario común para modificar metadatos de propiedades de dependencia consiste en modificar el valor predeterminado. Cambiar o agregar devoluciones de llamada del sistema de propiedades es un escenario más avanzado. Quizá desee hacerlo si la implementación de una clase derivada tiene diferentes interrelaciones entre propiedades de dependencia. Uno de los condicionantes de tener un modelo de programación que admita tanto código como el uso declarativo es que las propiedades deben poder establecerse en cualquier orden. En consecuencia, las propiedades dependientes deben establecerse en el momento, sin contexto, y no pueden apoyarse en el conocimiento de un orden de configuración, tal como el que podría encontrarse en un constructor. Para obtener más información sobre este aspecto del sistema de propiedades, vea Devoluciones de llamada y validación de las propiedades de dependencia. Observe que las devoluciones de llamada de la validación no forman parte de los metadatos; forman parte del identificador de propiedad de dependencia. Por consiguiente, las devoluciones de llamada de validación no se pueden modificar reemplazando metadatos.
En algunos casos, quizá desee también modificar las opciones de metadatos de propiedad del nivel de marco de trabajo de WPF en propiedades de dependencia existentes. Estas opciones comunican ciertos condicionales conocidos sobre propiedades del nivel de marco de trabajo de WPF a otros procesos del nivel de marco de trabajo de WPF tales como el sistema de diseño. La configuración de opciones, en general, solamente se hace cuando se registra una nueva propiedad de dependencia, pero también es posible cambiar los metadatos de la propiedad de nivel de marco de trabajo de WPF como parte de una llamada a OverrideMetadata o a AddOwner. Para ver los valores específicos a utilizar y más información, vea Metadatos de las propiedades de marco de trabajo. Para obtener más información relativa a cómo deben establecerse estas opciones para una propiedad de dependencia recién registrada, vea Propiedades de dependencia personalizadas.
Invalidar metadatos
El propósito de invalidar metadatos es, principalmente, ofrecer la oportunidad de modificar los diversos comportamientos derivados de metadatos que se aplican a la propiedad de dependencia tal como existe en el tipo. Las razones para ello se explican con más detalle en la sección Metadatos. Para obtener más información, incluidos algunos ejemplos de código, vea Cómo: Invalidar metadatos en una propiedad de dependencia.
Los metadatos de propiedad se pueden proporcionar para una propiedad de dependencia durante la llamada de registro (Register). Sin embargo, en muchos casos, quizá desee proporcionar metadatos específicos del tipo para la clase cuando herede esa propiedad de dependencia. Puede hacerlo llamando al método OverrideMetadata. Para ver un ejemplo de las APIs de WPF, la clase FrameworkElement es el tipo que registra en primer lugar la propiedad de dependencia Focusable. Sin embargo, la clase Control reemplaza los metadatos para la propiedad de dependencia, para proporcionar su propio valor predeterminado inicial, cambiándolo de false a true; por lo demás, reutiliza la implementación original de Focusable.
Cuando se reemplazan metadatos, las distintas características de los metadatos se combinan o se reemplazan.
PropertyChangedCallback se combina. Si agrega una nueva PropertyChangedCallback, esa devolución de llamada se almacena en los metadatos. Si no especifica una PropertyChangedCallback en la invalidación, el valor de PropertyChangedCallback se promueve como una referencia del antecesor más próximo que lo especifique en los metadatos.
El comportamiento real del sistema de propiedades para PropertyChangedCallback es que las implementaciones correspondientes a todos los propietarios de metadatos de la jerarquía se retienen y se agregan a una tabla, de tal forma que el orden de ejecución en el sistema de propiedades consiste en invocar primero las devoluciones de llamada de la clase más derivada.
Se reemplaza DefaultValue. Si no especifica una DefaultValue en la invalidación, el valor de DefaultValue procede del antecesor más próximo que lo especifique en los metadatos.
Se reemplazan las implementaciones de CoerceValueCallback. Si agrega una nueva CoerceValueCallback, esa devolución de llamada se almacena en los metadatos. Si no especifica una CoerceValueCallback en la invalidación, el valor de CoerceValueCallback se promueve como una referencia del antecesor más próximo que lo especifique en los metadatos.
El comportamiento del sistema de propiedades consiste en invocar únicamente la CoerceValueCallback de los metadatos inmediatos. Se retiene ninguna referencia a otras implementaciones de CoerceValueCallback en la jerarquía.
Este comportamiento se implementa mediante Merge y se puede invalidar en las clases de metadatos derivadas.
Invalidar metadatos de propiedades asociadas
En WPF, las propiedades asociadas se implementan como propiedades de dependencia. Esto significa que también tienen metadatos de propiedad, que las clases individuales pueden invalidar. Las consideraciones de ámbito para una propiedad asociada en WPF son generalmente que cualquier objeto DependencyObject puede tener una propiedad asociada establecida. Por consiguiente, cualquier clase derivada de DependencyObject puede invalidar los metadatos de cualquier propiedad asociada, pues podrían establecerse en una instancia de la clase. Puede invalidar valores predeterminados, devoluciones de llamada o propiedades de informe de características de nivel de marco de trabajo de WPF. Si la propiedad asociada se establece en una instancia de la clase, se aplicarán las características de los metadatos de la propiedad de reemplazo. Por ejemplo, puede invalidar el valor predeterminado, de modo que se informe del valor de invalidación como valor de la propiedad asociada en las instancias de la clase, siempre que la propiedad no se establezca de otra manera.
Nota |
---|
La propiedad Inherits no es relevante para propiedades asociadas. |
Agregar una clase como propietaria de una propiedad de dependencia existente
Una clase se puede agregar a sí misma como propietaria de una propiedad de dependencia que ya se haya registrado, utilizando el método AddOwner. Esto permite que la clase utilice una propiedad de dependencia registrada originalmente para un tipo diferente. La clase que se agrega no es, normalmente, una clase derivada del tipo que registró como propietario esa propiedad en primer lugar. En la práctica, esto permite que la clase y sus clases derivadas "hereden" una implementación de la propiedad de dependencia sin que la clase propietaria original y la clase que se agrega estén en la misma jerarquía de clases real. Además, la clase que se agrega (y todas las clases derivadas también) pueden proporcionar metadatos específicos del tipo de propiedad para la propiedad de dependencia original.
Además de agregarse a sí misma como propietaria mediante los métodos accesorios del sistema de propiedades, la clase que se agrega debe declarar miembros públicos adicionales en sí misma para convertir la propiedad de dependencia en un participante completo en el sistema de propiedades, con exposición tanto a código como a marcado. Una clase que agrega una propiedad de dependencia existente tiene las mismas responsabilidades en cuanto a la exposición del modelo de objetos para esa propiedad de dependencia como una clase que defina una nueva propiedad de dependencia personalizada. El primer miembro que se debe exponer es un campo identificador de la propiedad de dependencia. Este campo debe ser un campo public static readonly de tipo DependencyProperty, que esté asignado al valor que devuelve la llamada a AddOwner. El segundo miembro a definir es la propiedad "contenedora" de common language runtime (CLR). El contenedor hace que sea mucho más cómo manipular la propiedad de dependencia en el código (evita llamar cada vez a SetValue realizando esa llamada una sola vez en el propio contenedor). El contenedor se implementa de forma idéntica a cómo se implementaría si se estuviera registrando una propiedad de dependencia personalizada. Para obtener más información sobre cómo implementar una propiedad de dependencia, vea Propiedades de dependencia personalizadas y Cómo: Agregar un tipo de propietario para una propiedad de dependencia.
AddOwner y propiedades asociadas
Puede llamar a AddOwner para una propiedad de dependencia que la clase propietaria defina como propiedad asociada. Generalmente, la razón para hacerlo es exponer la propiedad previamente asociada como una propiedad de dependencia no asociada. A continuación expondrá el valor devuelto por AddOwner como un campo public static readonly para su uso como identificador de la propiedad de dependencia y definirá las propiedades "contenedoras" adecuadas para que la propiedad aparezca en la tabla de miembros y admita un uso de propiedad no asociado en la clase.