Uso de enlaces de datos en XAML
Los enlaces de datos se pueden declarar en código o en XAML mediante extensiones de marcado. En esta unidad se analiza esta última opción, ya que es la forma más habitual de crear enlaces. Hay un par de razones para preferir XAML. En primer lugar, la mayoría de los usuarios consideran que los enlaces forman parte del código de su interfaz de usuario porque obtienen datos para que la interfaz de usuario los muestre. En segundo lugar, hay una extensión de marcado denominada Binding
que facilita esta tarea.
¿Qué son los enlaces de datos?
Un enlace une dos propiedades. Una propiedad está en la interfaz de usuario y la otra en el objeto de modelo de datos. Si cambia el valor de una de las propiedades, el objeto de enlace puede actualizar la otra. En otras palabras, los enlaces son objetos intermedios que sincronizan los datos y la interfaz de usuario. Se usan los términos origen y destino para identificar los dos objetos implicados:
Origen: puede ser un objeto de cualquier tipo. En la práctica, normalmente se usa como origen un objeto de datos. Tiene que identificar la propiedad en ese objeto de origen para participar en el enlace. Para identificar la propiedad, establezca la propiedad
Path
en el enlace.Destino: El destino es una propiedad que se implementa mediante una propiedad especial denominada
BindableProperty
. El objeto con elBindableProperty
debe derivar deBindableObject
. Todos los controles proporcionados en .NET MAUI derivan deBindableObject
y la mayoría de sus propiedades sonBindableProperties
.
En el diagrama siguiente se muestra cómo un enlace es un objeto intermediario entre dos propiedades:
Cómo crear un enlace de datos en XAML
Echemos un vistazo a un enlace sencillo creado en XAML mediante la extensión de marcado {Binding}
. Enlaza la propiedad WeatherService.Humidity
del origen a la propiedad Text
del control de interfaz de usuario.
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<services:WeatherService x:Key="myWeatherService" />
</ResourceDictionary>
</VerticalStackLayout.Resources>
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
El origen de enlace es:
Instancia de objeto del tipo
WeatherService
. Se hace referencia a la instancia a través de la extensión de XAML{StaticResource ...}
, que apunta a un objeto del diccionario de recursos del diseño de la pila.El
Path
apunta a una propiedad denominadaHumidity
en el tipoWeatherService
.El
Path
es el primer parámetro sin nombre de la sintaxis{Binding}
, y la sintaxisPath=
puede omitirse. Estos dos enlaces son equivalentes:<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" /> <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
El destino de enlace es:
- El control
Label
. - La propiedad del control
Text
.
Cuando se muestra la interfaz de usuario, la extensión de XAML {Binding}
crea un enlace entre WeatherService
y Label
. El enlace lee el valor de la propiedad WeatherService.Humidity
en la propiedad Label.Text
.
Usar otro control como origen de enlace
Una característica útil del enlace es poder enlazar a otros controles. El código XAML siguiente es una demostración sencilla:
<VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label x:Name="TargetLabel" Text="TEXT TO ROTATE" BackgroundColor="Yellow" />
<Slider WidthRequest="100" Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource, Source={x:Reference TargetLabel}}" />
</VerticalStackLayout>
La propiedad Slider.Value
está enlazada con la propiedad Label.Rotation
, pero de una forma diferente a la explicada anteriormente. Esta propiedad usa el modo de enlace OneWayToSource
, que invierte el mecanismo de enlace típico. En lugar de que el Origen actualice el Destino, el OneWayToSource
actualiza el Origen cuando cambia el Destino. En este ejemplo, cuando el control deslizante se mueve, actualiza la rotación de la etiqueta en función del valor del control deslizante, como se ilustra en la siguiente animación:
El escenario típico para enlazar controles entre sí es cuando un control, normalmente un control de colección como un ListView
o CarouselView
, tiene un elemento seleccionado que se quiere usar como origen de datos. En el ejemplo de una página que muestra la previsión del tiempo, podría tener una ListView
que presente una previsión para cinco días. Cuando el usuario selecciona un día de la lista, los detalles de ese pronóstico del tiempo aparecen en otros controles. Si el usuario selecciona otro día, los demás controles se actualizan de nuevo con los datos del día seleccionado.
Uso del mismo origen para varios enlaces
En el ejemplo anterior se mostró el uso de un recurso estático como origen para un único enlace. Ese origen se puede usar en varios enlaces. Este es un ejemplo de declaración de un enlace en tres controles diferentes, todos vinculados al mismo objeto y propiedad Path
, aunque algunos omiten la propiedad Path
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
No es necesario usar el mismo Path
cuando se usa el mismo Source
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Temperature, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
Rara vez se presenta un único dato de un origen, aunque podría ocurrir. Suele tener varios controles que usan distintos datos de un mismo origen. Esta situación es tan común que la clase BindableObject
tiene una propiedad llamada BindingContext
que funciona como origen para el enlace de datos. Recuerde que los controles MAUI .NET heredan de la clase BindableObject
, por lo que los controles MAUI .NET tienen la propiedad BindingContext
.
Establecer el Source
del enlace es opcional. El enlace que no tiene Source
establecido busca automáticamente en el árbol visual XAML un BindingContext
, que está establecido en el XAML o asignado a un elemento principal por el código. Los enlaces se evalúan siguiendo este patrón:
Si el enlace define un
Source
, se usa ese origen y se detiene la búsqueda. ElPath
del enlace se aplica alSource
para obtener un valor. Si no se estableceSource
, comienza la búsqueda de un origen de enlace.La búsqueda comienza con el propio objeto de destino. Si el
BindingContext
del objeto de destino no es null, la búsqueda se detiene y elPath
del enlace se aplica alBindingContext
para obtener un valor. Si elBindingContext
es null, la búsqueda continúa.Este proceso continúa hasta que llega a la raíz XAML. La búsqueda finaliza comprobando el
BindingContext
de la raíz de un valor que no es NULL. Si no se encontró ningúnBindingContext
válido, el enlace no tiene nada que enlazar y no hace nada.
Es habitual establecer el BindingContext
en el nivel del objeto raíz, para aplicarlo a todo el XAML.
Hay una última característica conveniente que merece la pena mencionar. Los enlaces observan los cambios en la referencia de objetos de su origen. Esto funciona incluso para los enlaces que usan BindingContext
como origen. Si se reasigna Source
o BindingContext
a otro objeto, los enlaces obtienen los datos del origen nuevo y actualizan su destino.