Resumen del capítulo 16. Enlace de datos
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.
Los programadores a menudo se encuentran escribiendo controladores de eventos que detectan cuándo ha cambiado una propiedad de un objeto, y lo usan para cambiar el valor de una propiedad en otro objeto. Este proceso se puede automatizar con la técnica del enlace de datos. Los enlaces de datos se definen normalmente en XAML y pasan a formar parte de la definición de la interfaz de usuario.
A menudo, estos enlaces de datos conectan objetos de la interfaz de usuario a los datos subyacentes. Se trata de una técnica que se explora con mayor profundidad en el Capítulo 18. MVVM. Sin embargo, los enlaces de datos también pueden conectar dos o más elementos de la interfaz de usuario. La mayoría de los ejemplos anteriores de enlace de datos de este capítulo demuestran esta técnica.
Conceptos básicos del enlace
Varias propiedades, métodos y clases están implicados en el enlace de datos:
- La clase
Binding
se deriva deBindingBase
y encapsula muchas características de un enlace de datos. - La propiedad
BindingContext
se define mediante la claseBindableObject
. - El método
SetBinding
también se define en la claseBindableObject
. - La clase
BindableObjectExtensions
define tres métodos deSetBinding
adicionales.
Las dos clases siguientes admiten las extensiones de marcado XAML para los enlaces:
BindingExtension
admite la extensión de marcadoBinding
ReferenceExtension
admite la extensión de marcadox:Reference
Hay dos interfaces implicadas en el enlace de datos:
INotifyPropertyChanged
en el espacio de nombresSystem.ComponentModel
sirve para implementar la notificación cuando cambia una propiedad.IValueConverter
se utiliza para definir las clases pequeñas que convierten los valores de un tipo a otro en los enlaces de datos.
Un enlace de datos conecta dos propiedades del mismo objeto, o (más comúnmente) dos objetos diferentes. Estas dos propiedades se denominan origen y destino. Normalmente, un cambio en la propiedad de origen hace que se produzca un cambio en la propiedad de destino, pero a veces se invierte la dirección. En cualquier caso:
- La propiedad target debe estar respaldada por
BindableProperty
. - Por lo general, la propiedad source es miembro de una clase que implementa
INotifyPropertyChanged
.
Una clase que implementa INotifyPropertyChanged
activa un evento PropertyChanged
cuando una propiedad cambia de valor. BindableObject
implementa INotifyPropertyChanged
y activa automáticamente un evento PropertyChanged
cuando una propiedad respaldada por BindableProperty
cambia valores, pero puede escribir sus propias clases que implementan INotifyPropertyChanged
sin que se deriven de BindableObject
.
Código y XAML
En el ejemplo OpacityBindingCode se muestra cómo establecer un enlace de datos en el código:
- El origen es la propiedad
Value
deSlider
. - El destino es la propiedad
Opacity
deLabel
.
Los dos objetos se conectan estableciendo el BindingContext
del objeto Label
en el objeto Slider
. Las dos propiedades se conectan llamando a un método de extensión SetBinding
en el Label
que hace referencia a la propiedad enlazable OpacityProperty
y la propiedad Value
de Slider
expresada como una cadena.
La manipulación de la Slider
provoca que Label
aparezca y desaparezca gradualmente de la vista.
El programa OpacityBindingXaml es el mismo con el enlace de datos establecido en XAML. BindingContext
de Label
se establece en una extensión de marcado de x:Reference
que hace referencia a Slider
, y la propiedad Opacity
de Label
se establece en la extensión de marcado Binding
con su propiedad Path
que hace referencia a la propiedad Value
de Slider
.
Source y BindingContext
En el ejemplo BindingSourceCode se muestra un enfoque alternativo en el código. Para crear un objeto Binding
, establezca la propiedad Source
en el objeto Slider
y la propiedad Path
en "Value". A continuación, se llama al método SetBinding
de BindableObject
en el objeto Label
.
También se podría haber utilizado el constructor Binding
para definir el objeto Binding
.
En el ejemplo BindingSourceXaml se muestra la técnica comparable en XAML. La propiedad Opacity
de Label
se establece en una extensión de marcado de Binding
con Path
establecido en la propiedad Value
y Source
establecida en una extensión de marcado x:Reference
insertada.
En resumen, hay dos maneras de hacer referencia al objeto de origen de enlace:
- A través de la propiedad
BindingContext
del destino. - A través de la propiedad
Source
del propio objetoBinding
.
Si se especifican ambos, la segunda tiene prioridad. La ventaja de la BindingContext
es que se propaga a través del árbol visual. Esto es muy útil si varias propiedades de destino están enlazadas al mismo objeto de origen.
El programa WebViewDemo muestra esta técnica con el elemento WebView
. Dos elementos Button
para navegar hacia atrás y hacia delante heredan un objeto BindingContext
de su elemento primario que hace referencia a WebView
. Las propiedades de IsEnabled
de los dos botones tienen extensiones de marcado de Binding
simples que tienen como destino las propiedades IsEnabled
del botón basadas en la configuración de las propiedades CanGoBack
y CanGoForward
de solo lectura de WebView
.
Modo de enlace
Establezca la propiedad Mode
de Binding
en un miembro de la enumeración BindingMode
:
OneWay
para que los cambios en la propiedad de origen afecten al destino.OneWayToSource
para que los cambios en la propiedad de destino afecten al origen.TwoWay
para que los cambios en el origen y el destino se afecten entre sí.Default
para usar el valorDefaultBindingMode
especificado cuando se creó el valorBindableProperty
de destino. Si no se especifica ninguno, el valor predeterminado esOneWay
para las propiedades normales enlazables yOneWayToSource
para las propiedades enlazables de solo lectura.
Nota:
La enumeración de BindingMode
ahora también incluye OnTime
para aplicar un enlace solo cuando cambia el contexto de enlace y no cuando cambia la propiedad de origen.
Las propiedades que es probable que sean los destinos de los enlaces de datos en escenarios de MVVM generalmente tienen un valor DefaultBindingMode
de TwoWay
. Dichos componentes son:
- Propiedad
Value
deSlider
yStepper
- Propiedad
IsToggled
deSwitch
- Propiedad
Text
deEntry
,Editor
ySearchBar
. - Propiedad
Date
deDatePicker
- Propiedad
Time
deTimePicker
En el ejemplo BindingModes se muestran los cuatro modos de enlace con un enlace de datos, donde el destino es la propiedad FontSize
de un elemento Label
y el origen es la propiedad Value
de un elemento Slider
. Esto permite que cada Slider
controle el tamaño de fuente del Label
correspondiente. Sin embargo, los elementos Slider
no se inicializan porque el DefaultBindingMode
de la propiedad FontSize
es OneWay
.
El ejemplo ReverseBinding establece los enlaces en la propiedad Value
del Slider
que hace referencia a la propiedad FontSize
de cada Label
. Parece que va para atrás, pero funciona mejor al inicializar los elementos Slider
porque la propiedad Value
de Slider
tiene un DefaultBindingMode
de TwoWay
.
Esto es análogo a la forma en que se definen los enlaces en MVVM, y usará este tipo de enlace con frecuencia.
Formato de cadena
Cuando la propiedad de destino es de tipo string
, puede usar la propiedad StringFormat
definida por BindingBase
para convertir el origen en string
. Establezca la propiedad StringFormat
en una cadena de formato de .NET que se usaría con el formato String.Format
estático para mostrar el objeto. Al utilizar esta cadena de formato dentro de una extensión de marcado, inclúyala entre comillas simples para que las llaves no se confundan en el caso de una extensión de marcado insertada.
En el ejemplo ShowViewValues se muestra cómo utilizar StringFormat
en XAML.
En el ejemplo WhatSizeBindings se demuestra cómo mostrar el tamaño de la página con enlaces a las propiedades Width
y Height
de ContentPage
.
¿Por qué se denomina "Path"?
La propiedad Path
de Binding
se llama así porque puede ser una serie de propiedades e indexadores separados por puntos. En el ejemplo BindingPathDemos se muestran varios ejemplos.
Enlace de convertidores de valores
Cuando las propiedades de origen y de destino de un enlace son tipos diferentes, puede aplicar conversiones a los tipos mediante un convertidor de enlace. Se trata de una clase que implementa la interfaz IValueConverter
y contiene dos métodos: Convert
para convertir el origen en destino y ConvertBack
para convertir el destino en origen.
La clase IntToBoolConverter
de la biblioteca Xamarin.FormsBook.Toolkit es un ejemplo de cómo convertir int
en bool
. Se demuestra en el ejemplo ButtonEnabler, que solo habilita Button
si se ha escrito al menos un carácter en Entry
.
La clase BoolToStringConverter
convierte bool
en string
y define dos propiedades para especificar qué texto se debe devolver para los valores false
y true
.
BoolToColorConverter
es similar. En el ejemplo SwitchText se muestra el uso de estos dos convertidores para mostrar textos distintos en diferentes colores basados en una configuración de Switch
.
El valor BoolToObjectConverter
genérico puede reemplazar a BoolToStringConverter
y BoolToColorConverter
y servir como convertidor generalizado de bool
a objeto de cualquier tipo.
Enlaces y vistas personalizadas
Puede simplificar los controles personalizados mediante enlaces de datos. El archivo de código NewCheckBox.cs
define las propiedades Text
, TextColor
, FontSize
, FontAttributes
y IsChecked
, pero no tiene ninguna lógica para los objetos visuales del control.
En su lugar, el archivo NewCheckBox.cs.xaml
contiene todo el marcado de los objetos visuales del control a través de enlaces de datos en los elementos Label
basados en las propiedades definidas en el archivo de código subyacente.
En el ejemplo NewCheckBoxDemo se muestra el control personalizado de NewCheckBox
.