Comparar uma interface do usuário controlada por eventos com uma interface do usuário associada a dados
- 6 minutos
Uma interface de usuário orientada a eventos é projetada em torno dos eventos que um controle expõe. Esses eventos podem ser associados ao código do manipulador de eventos que é invocado quando o evento é disparado. Por exemplo, digamos que você tenha um botão que, quando clicado, executa uma operação de execução prolongada. O manipulador de eventos atribuído ao evento Clicked pode iniciar a operação e, em seguida, definir a propriedade do botão IsEnabled como false, impedindo que o botão seja clicado novamente enquanto a operação estiver em execução.
Uma interface do usuário associada a dados usa a associação de dados para apresentar e interagir com os dados. As propriedades dos controles são associadas às propriedades do objeto de dados e essas associações podem detectar alterações nas propriedades. Usando o exemplo anterior, considere o botão que executa uma operação de execução longa. Em vez de desabilitar o botão em code-behind, a propriedade IsEnabled é associada à propriedade do objeto de dados IsBusy. Sempre que o objeto de dados se torna "ocupado", o estado habilitado do botão é alterado automaticamente para corresponder.
Prós e contras do uso de eventos e code-behind
Usar o manipulador de eventos do controle com code-behind é uma maneira rápida e conveniente de projetar a lógica do aplicativo para sua interface do usuário. Você usa código para chamar serviços para obter dados, executar operações nesses dados e interagir com os controles na página. O código é usado para manter a interface do usuário e os dados sincronizados.
Considere o exemplo de um aplicativo de serviço de clima. O fragmento XAML a seguir contém um botão simples de interface de usuário que o usuário seleciona para obter os dados mais recentes e atualizar a exibição com a umidade.
<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>
Há três controles nomeados neste exemplo:
- Controle
Entrychamado PostalCode. - Controle
Buttonchamado RefreshWeatherButton. - Controle
Labelchamado Umidade.
O RefreshWeatherButton tem um manipulador de eventos declarado para o evento Clicked. Quando o botão é clicado, o manipulador de eventos consulta um serviço de previsão do tempo para obter a previsão mais recente, usando os dados inseridos no PostalCode controle de entrada, e atualiza o texto do Humidity rótulo para mostrar a umidade atual.
private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
WeatherService.Location = PostalCode.Text;
WeatherService.Refresh();
Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}
Neste manipulador de eventos, três controles são firmemente acoplados uns aos outros e aos dados por meio do code-behind.
Esse design funciona muito bem para pequenas interfaces do usuário, mas assim que a interface do usuário se torna complexa, manter um code-behind firmemente acoplado pode se tornar problemático. Se você excluir ou alterar um controle, você deverá limpar qualquer código que houver usando esses controles de interface do usuário, o que pode incluir o manipulador de eventos. Se você decidir reprojetar a interface do usuário, terá muito código para refatorar também. E quando a estrutura de dados de backup é alterada, você precisa se aprofundar no código de cada interface do usuário para permanecer sincronizado.
Associar dados ajuda
Você pode implementar associações de dados em XAML ou código, mas elas são muito mais comuns em XAML, em que ajudam a reduzir o tamanho do arquivo code-behind. Quando você substitui o código processual em manipuladores de eventos por código declarativo ou marcação, o aplicativo é simplificado e esclarecido. Como as associações não exigem code-behind, você pode criar, alterar ou redesenhar facilmente a interface do usuário para se ajustar à forma como deseja apresentar os dados.
Vamos usar o mesmo exemplo da seção anterior, mas atualizá-lo para usar a associação de dados:
<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>
Você pode identificar as propriedades associadas a dados, elas usam a sintaxe de extensão XAML {Binding ...} para o valor da propriedade. Não se preocupe com os detalhes ainda; abordaremos isso posteriormente neste módulo.
Os mesmos três controles são declarados no XAML, mas nenhum deles é nomeado, porque um nome não é necessário:
Entrycontrole: a propriedade desseTextcontrole está associada a uma propriedade chamadaLocation.Buttoncontrol: A propriedade doCommandbotão está associada a uma propriedade chamadaRefreshWeather.Commandé uma propriedade no botão que invoca o código quando o botão é pressionado. É uma alternativa ao eventoClickedusado na associação de dados.Labelcontrole: essaTextpropriedade está associada a uma propriedade chamadaHumidity.
Nesta interface do usuário simples, todo o code-behind é eliminado. Remover todo o code-behind não é o objetivo da associação de dados, mesmo que isso seja possível. O code-behind ainda tem sua utilidade. A quantidade de associação de dados que você implementa cabe a você.
Agora, a interface do usuário está flexívelmente acoplada a um objeto de dados. Por que ela está fracamente acoplada em vez de firmemente acoplada? Isso se deve à maneira como as associações são avaliadas. Cada controle tem uma propriedade BindingContext. Se o contexto não estiver definido, o contexto do controle pai será usado e assim por diante, até que a raiz do XAML seja avaliada. Quando as associações são avaliadas, a instância de objeto do contexto é verificada quanto às propriedades necessárias, como a associação Text do controle de rótulo à propriedade do contexto Humidity. Se Humidity não existir no contexto, nada acontecerá.
Como a interface do usuário está vagamente acoplada, você pode reprojetar a interface do usuário sem se preocupar com quebra de código. No entanto, você pode interromper a funcionalidade. Por exemplo, você pode excluir o botão e o aplicativo ainda compila e executa, mas não há uma maneira de atualizar o clima. Por outro lado, você pode substituir o controle Entry e Button pelo controle único SearchBar. Esse controle permite inserir texto e invocar um comando.
<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />
Como você pode ver, usar a associação de dados em seu design de interface do usuário pode ajudar você a evoluir e alterar sua interface do usuário sem muito trabalho. Ele mantém a interface do usuário sincronizada com os dados automaticamente e a lógica do aplicativo é separada da interface do usuário.