Comparación de una interfaz de usuario controlada por eventos con una interfaz de usuario enlazada a datos

Completado

Una interfaz de usuario (UI) controlada por eventos se diseña en torno a los eventos que expone un control. Estos eventos pueden asociarse a un código controlador de eventos que se invoca cuando se desencadena el evento. Por ejemplo, supongamos que tiene un botón que al pulsarlo realiza una operación de larga duración. El controlador de eventos asignado al evento Clicked podría iniciar la operación y después establecer la propiedad IsEnabled del botón en false, impidiendo que se vuelva a pulsar el botón mientras se ejecuta la operación.

Una interfaz de usuario vinculada a datos usa el enlace de datos para presentar los datos e interactuar con ellos. Las propiedades de los controles se enlazan a las propiedades del objeto de datos y esos enlaces pueden detectar cambios en las propiedades. Con el ejemplo anterior, considere el botón que realiza una operación de larga duración. En lugar de deshabilitar el botón en el código subyacente, la propiedad IsEnabled se vincula a la propiedad IsBusy del objeto de datos. Cada vez que el objeto de datos pasa a estar "ocupado", el estado habilitado del botón se cambia automáticamente para que coincida.

Ventajas y desventajas de usar eventos y código subyacente

Usar el controlador de eventos del control con código subyacente es una forma rápida y cómoda de diseñar la lógica de la aplicación para su interfaz de usuario. El código se usa para llamar a servicios para obtener datos, realizar operaciones con esos datos e interactuar con los controles de la página. El código se usa para mantener sincronizados la interfaz de usuario y los datos.

Considere el ejemplo de una aplicación del servicio meteorológico. El siguiente fragmento de XAML contiene un sencillo botón de interfaz de usuario que el usuario selecciona para obtener los últimos datos y actualizar la interfaz de usuario con la humedad.

<VerticalStackLayout Margin="10">
    <HorizontalStackLayout Spacing="20">
        <Label Text="Postal Code:" VerticalOptions="Center" />
        <Entry x:Name="PostalCode" WidthRequest="100" />
        <Button x:Name="RefreshWeatherButton" Text="Refresh" WidthRequest="200" Clicked="RefreshWeatherButton_Clicked" />
    </HorizontalStackLayout>
    <Label x:Name="Humidity" Text="Humidity: ?" />
</VerticalStackLayout>

Captura de pantalla de una aplicación .NET MAUI que tiene un control de entrada para un código postal, un botón con la actualización de texto. En esos dos controles hay una etiqueta que representa la humedad.

En este ejemplo hay tres controles con nombre:

  • Control de Entry denominado PostalCode.
  • Control de Button denominado RefreshWeatherButton.
  • Control de Label denominado Humidity.

El RefreshWeatherButton tiene un controlador de eventos declarado para el evento Clicked. Cuando se pulsa el botón, el controlador de eventos consulta a un servicio meteorológico la última previsión del tiempo, usando los datos escritos en el control de entrada de PostalCode, y establece el texto de la etiqueta de Humidity en la humedad actual.

private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
    WeatherService.Location = PostalCode.Text;
    WeatherService.Refresh();
    Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}

En este controlador de eventos, tres controles se acoplan estrechamente entre sí y los datos a través del código subyacente.

Este diseño funciona muy bien para UI pequeñas, pero en cuanto la UI se vuelve compleja, mantener un código subyacente estrechamente acoplado puede resultar problemático. Si quiere eliminar o cambiar un control, debe limpiar cualquier código que use esos controles de interfaz de usuario, lo que podría incluir el controlador de eventos. Si decide rediseñar la interfaz de usuario, también tendrá mucho código que refactorizar. Y cuando la estructura de datos de respaldo vuelve a cambiar, hay que profundizar en el código de cada interfaz de usuario para mantener la sincronización.

Ayuda del enlace de datos

Los enlaces de datos pueden implementarse en XAML o en código, pero son mucho más comunes en XAML, donde ayudan a reducir el tamaño del archivo de código subyacente. Al reemplazar el código de procedimientos en los controladores de eventos con código declarativo o marcado, se simplifica y se aclara la aplicación. El enlace no requiere código subyacente, por lo que podrá crear, modificar o rediseñar fácilmente la interfaz de usuario para adaptarla a la forma en que desee presentar los datos.

Tomemos el mismo ejemplo que en la sección anterior, pero actualicémoslo para usar el enlace de datos:

<VerticalStackLayout Margin="10">
    <HorizontalStackLayout Spacing="20">
        <Label Text="Postal Code:" VerticalOptions="Center" />
        <Entry Text="{Binding Location, Mode=OneWayToSource}" WidthRequest="100" />
        <Button Text="Refresh" Command="{Binding RefreshWeather}" WidthRequest="200" />
    </HorizontalStackLayout>
    <Label Text="{Binding Humidity}" />
</VerticalStackLayout>

Puede detectar las propiedades que están vinculadas a datos, ya que usan la sintaxis de extensión {Binding ...} de XAML para el valor de la propiedad. No se preocupe aún por los detalles, que se tratan más adelante en este módulo.

Los mismos tres controles se declaran en el XAML, pero ninguno de ellos se denomina, ya que no se requiere un nombre:

  • Control Entry:

    La propiedad Text de este control está enlazada a una propiedad denominada Location.

  • Control Button:

    La propiedad Command del botón está enlazada a una propiedad denominada RefreshWeather. Command es una propiedad del botón que invoca código cuando se presiona el botón. Es una alternativa al evento Clicked que se usa en el enlace de datos.

  • Control Label:

    Esta propiedad Text está enlazada a una propiedad denominada Humidity.

En esta interfaz de usuario simple, se elimina todo el código subyacente. Eliminar todo el código subyacente no es el objetivo del enlace de datos, aunque suele ser posible. El código subyacente todavía tiene su lugar. La cantidad de enlace de datos que implemente depende de usted.

Ahora la interfaz de usuario está acoplada de forma flexible a un objeto de datos. ¿Por qué está acoplada de forma flexible en lugar de estrechamente acoplada? Debido a la forma en que se evalúan los enlaces. Cada control tiene una propiedad BindingContext. Si no se establece el contexto, se usa el contexto del control primario, etc., hasta que se evalúe la raíz del XAML. Cuando se evalúan los enlaces, se comprueba si la instancia del objeto del contexto tiene las propiedades necesarias, como el enlace Text del control de etiqueta con la propiedad Humidity del contexto. Si Humidity no existe en el contexto, no sucede nada.

Dado que la interfaz de usuario está acoplada de forma flexible, puede rediseñar la interfaz de usuario sin preocuparse de interrumpir el código. Sin embargo, puede interrumpir la funcionalidad. Por ejemplo, puede eliminar el botón y la aplicación todavía compila y se ejecuta, pero no tiene una manera de actualizar el tiempo. Por otro lado, podría reemplazar los controles Entry y Button por el control único SearchBar. Este control le permite escribir texto e invocar un comando.

<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />

Como puede ver, el uso del enlace de datos en el diseño de la interfaz de usuario puede ayudarle a evolucionar y cambiar la interfaz de usuario sin mucho trabajo. Mantiene la interfaz de usuario sincronizada con los datos automáticamente y la lógica de la aplicación está separada de la interfaz de usuario.

Comprobación de conocimientos

1.

¿Cuál de las siguientes instrucciones describe cómo mejora el enlace de datos la interfaz de usuario?

2.

En una aplicación que recupera el tiempo más reciente, un control de etiqueta que representa la temperatura está enlazado al objeto de datos. Cuando el usuario pulsa el botón "Obtener el tiempo", desencadenando el evento Clicked, ¿qué haría el código del controlador de eventos para actualizar la interfaz de usuario?