Uso de enlaces de datos en XAML

Completado

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 el BindableProperty debe derivar de BindableObject. Todos los controles proporcionados en .NET MAUI derivan de BindableObject y la mayoría de sus propiedades son BindableProperties.

En el diagrama siguiente se muestra cómo un enlace es un objeto intermediario entre dos propiedades:

Diagrama que muestra un enlace como un intermediario entre una propiedad de objeto de origen y una propiedad enlazable de objeto de destino.

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 denominada Humidity en el tipo WeatherService.

    El Path es el primer parámetro sin nombre de la sintaxis {Binding}, y la sintaxis Path= 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:

Imagen animada de un control deslizante que se arrastra con un ratón. A medida que se mueve el control deslizante, un fragmento de texto gira para que coincida con la posición del control deslizante.

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:

  1. Si el enlace define un Source, se usa ese origen y se detiene la búsqueda. El Path del enlace se aplica al Source para obtener un valor. Si no se establece Source, comienza la búsqueda de un origen de enlace.

  2. 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 el Path del enlace se aplica al BindingContext para obtener un valor. Si el BindingContext es null, la búsqueda continúa.

  3. 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ún BindingContext 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.

Comprobación de conocimientos

1.

¿Qué es cierto sobre el objeto de origen en un enlace de .NET MAUI?

2.

¿Qué es cierto sobre la propiedad de destino en el enlace de .NET MAUI?

3.

Si todos los enlaces de los controles de un Grid necesitan el mismo objeto de origen, ¿cuál es la estrategia más segura para establecer el objeto de origen una sola vez?