Compartir a través de


Resumen del capítulo 11. La infraestructura enlazable

Nota:

Este libro se publicó en la primavera de 2016 y no se ha actualizado desde entonces. Gran parte del libro sigue siendo útil, pero algunos de los materiales están anticuados y algunos temas ya no son completamente correctos o completos.

Cada programador de C# está familiarizado con las propiedades de C#. Las propiedades contienen un descriptor de acceso set o un descriptor de acceso get. A menudo se les llama propiedades de CLR en el contexto de Common Language Runtime.

Xamarin.Forms establece una definición de propiedad mejorada denominada propiedad enlazable encapsulada por la clase BindableProperty y admitida por la clase BindableObject. Estas clases están relacionadas pero son bastante distintas: BindableProperty se usa para definir la propia propiedad; BindableObject es como object en que es una clase base para las clases que definen propiedades enlazables.

Jerarquía de clases de Xamarin.Forms

En el ejemplo ClassHierarchy se usa la reflexión para mostrar una jerarquía de clases de Xamarin.Forms y mostrar el rol fundamental que desempeña BindableObject en esta jerarquía. BindableObject se deriva de Object y es la clase primaria de Element de la que se deriva VisualElement. Se trata de la clase primaria de Page y View, que es la clase primaria de Layout:

Captura de pantalla triple de uso compartido de jerarquía de clases

Un vistazo a BindableObject y BindableProperty

En las clases que derivan de BindableObject muchas propiedades de CLR se dice que están "respaldadas" por las propiedades enlazables. Por ejemplo, la propiedad Text de la clase Label es una propiedad de CLR, pero la clase Label también define un campo público estático de solo lectura denominado TextProperty de tipo BindableProperty.

Una aplicación puede establecer u obtener la propiedad Text de Label normalmente, o bien la aplicación puede establecer Text llamando al método SetValue definido por BindableObject con un argumento Label.TextProperty. Del mismo modo, una aplicación puede obtener el valor de la propiedad Text llamando al método GetValue, de nuevo con un argumento Label.TextProperty. Esto se muestra en el ejemplo PropertySettings.

La propiedad de CLR Text incluso se implementa por completo con los métodos SetValue y GetValue definidos por BindableObject junto con la propiedad estática Label.TextProperty.

BindableObject y BindableProperty proporcionan compatibilidad con:

  • Asignar valores predeterminados a propiedades
  • Almacenar sus valores actuales
  • Proporcionar mecanismos para validar valores de propiedad
  • Mantener la coherencia entre las propiedades relacionadas en una única clase
  • Responder a los cambios de propiedad
  • Desencadenar notificaciones cuando una propiedad está a punto de cambiar o ha cambiado
  • Admitir el enlace de datos
  • Admitir estilos
  • Admitir recursos dinámicos

Cada vez que cambia una propiedad respaldada por una propiedad enlazable, BindableObject desencadena un evento PropertyChanged que identifica la propiedad que ha cambiado. Este evento no se desencadena cuando la propiedad se establece en el mismo valor.

Algunas propiedades no están respaldadas por propiedades enlazables y algunas clases de Xamarin.Forms, como Span, no se derivan de BindableObject. Solo una clase que se deriva de BindableObject puede admitir propiedades enlazables porque BindableObject define los métodos SetValue y GetValue.

Dado que Span no se deriva de BindableObject, ninguna de sus propiedades, como Text, están respaldadas por una propiedad enlazable. Esta es la razón por la que un valor DynamicResource en la propiedad Text de Span produce una excepción en el ejemplo DynamicVsStatic del capítulo anterior. En el ejemplo DynamicVsStaticCode se muestra cómo establecer recursos dinámicos en el código mediante el método SetDynamicResource definido por Element. El primer argumento es un objeto de tipo BindableProperty.

Del mismo modo, el método SetBinding definido por BindableObject tiene un primer argumento de tipo BindableProperty.

Definición de propiedades enlazables

Puede definir sus propias propiedades enlazables mediante el método estático BindableProperty.Create para crear un campo estático de solo lectura de tipo BindableProperty.

Esto se muestra en la clase AltLabel de la biblioteca Xamarin.FormsBook.Toolkit. La clase se deriva de Label y permite especificar un tamaño de fuente en puntos. Se muestra en el ejemplo PointSizedText.

Se requieren cuatro argumentos del método BindableProperty.Create:

  • propertyName: el nombre de texto de la propiedad (el mismo que el nombre de la propiedad de CLR)
  • returnType: el tipo de la propiedad de CLR
  • declaringType: el tipo de la clase que declara la propiedad.
  • defaultValue: el valor predeterminado de la propiedad

Dado que defaultValue es de tipo object, el compilador debe ser capaz de determinar el tipo del valor predeterminado. Por ejemplo, si returnType es double, defaultValue debe establecerse en algo como 0,0 en lugar de solo en 0, o la falta de coincidencia de tipos desencadenará una excepción en tiempo de ejecución.

También es muy común que una propiedad enlazable incluya:

  • propertyChanged: un método estático al que se llama cuando cambia el valor de la propiedad. El primer argumento es la instancia de la clase cuya propiedad ha cambiado.

Los demás argumentos para BindableProperty.Create no son tan comunes:

  • defaultBindingMode: se usa en relación con el enlace de datos (como se describe en Capítulo 16. Enlace de datos)
  • validateValue: devolución de llamada para comprobar si hay un valor válido.
  • propertyChanging: devolución de llamada que indica cuándo está a punto de cambiar la propiedad.
  • coerceValue: devolución de llamada para convertir un valor establecido en otro valor.
  • defaultValueCreate: devolución de llamada para crear un valor predeterminado que no se puede compartir entre las instancias de la clase (por ejemplo, una colección).

Propiedad enlazable de solo lectura.

Una propiedad enlazable puede ser de solo lectura. La creación de una propiedad enlazable de solo lectura requiere una llamada al método estático BindableProperty.CreateReadOnly para definir un campo de solo lectura estático privado de tipo BindablePropertyKey.

A continuación, defina el descriptor de acceso set de la propiedad de CLR como private para llamar a una sobrecarga SetValue con el objeto BindablePropertyKey. Esto evita que la propiedad se establezca fuera de la clase.

Esto se muestra en la clase CountedLabel utilizada en el ejemplo BaskervillesCount.