Comparar uma interface do usuário orientada a eventos com uma interface do usuário vinculada a dados
- {númeroDeMinutos} minutos
Uma interface do 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 é acionado. Por exemplo, digamos que você tenha um botão que, quando clicado, executa uma operação de longa duração. O manipulador de eventos atribuído ao Clicked evento pode iniciar a operação e, em seguida, definir a propriedade do IsEnabled botão como false, impedindo que o botão seja clicado novamente enquanto a operação está em execução.
Uma interface do usuário vinculada a dados usa a vinculação de dados para apresentar e interagir com dados. As propriedades dos controles são vinculadas às propriedades do objeto de dados, e essas associações podem detetar alterações nas propriedades. Usando o exemplo anterior, considere o botão que executa uma operação de longa duração. Em vez de desativar o botão no code-behind, a propriedade IsEnabled é associada à propriedade de dados do objeto IsBusy. Sempre que o objeto de dados se torna "ocupado", o estado ativado do botão é automaticamente alterado 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 o 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 meteorológico. O fragmento XAML a seguir contém um botão de UI simples que o utilizador seleciona para obter os dados mais recentes e atualizar a UI 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:
-
Entrycontrole chamado PostalCode. -
Buttoncontrolo chamado RefreshWeatherButton. -
Labelcontrolo chamado Humidade.
O RefreshWeatherButton tem um manipulador de eventos declarado para o Clicked evento. Quando o botão é clicado, o manipulador de eventos consulta um serviço meteorológico para obter a previsão do tempo mais recente usando os dados inseridos no controle de entrada PostalCode, e define o texto do rótulo Humidity para 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 estão firmemente acoplados entre si e aos dados através do código subjacente.
Esse design funciona muito bem para pequenas UIs, mas assim que a interface de utilizador se torna complexa, manter um "code-behind" estreitamente acoplado pode tornar-se problemático. Se você excluir ou alterar um controle, deverá limpar qualquer código usando esses controles de interface do usuário, que podem incluir o manipulador de eventos. Se você decidir redesenhar a interface do usuário, também terá muito código para refatorar. E quando a estrutura de dados de backup muda, você precisa mergulhar no código de cada interface do usuário para ficar sincronizado.
A vinculação de dados ajuda
Você pode implementar associações de dados em XAML ou código, mas elas são muito mais comuns em XAML, onde ajudam a reduzir o tamanho do arquivo code-behind. Quando você substitui o código de procedimento 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 pegar o mesmo exemplo da seção anterior, mas atualizá-lo para usar a vinculaçã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 que estão vinculadas a dados, elas usam a sintaxe {Binding ...} da extensão XAML para o valor da propriedade. Não se preocupe com os detalhes ainda; abordaremos isso mais adiante neste módulo.
Os mesmos três controles são declarados no XAML, mas nenhum deles é nomeado, porque um nome não é necessário:
Entrycontrol: A propriedade desteTextcontrole está vinculada a uma propriedade chamadaLocation.Buttoncontrol: A propriedade doCommandbotão está vinculada a uma propriedade chamadaRefreshWeather.Commandé uma propriedade no botão que invoca o código quando o botão é pressionado. É uma alternativa aoClickedevento usado na vinculação de dados.Labelcontrol: EstaTextpropriedade está vinculada a uma propriedade chamadaHumidity.
Nesta interface de utilizador simples, todo o código subjacente é eliminado. Remover todo o code-behind não é o objetivo da vinculação de dados, embora seja possível. Code-behind ainda tem o seu lugar. A quantidade de vinculação de dados que você implementa depende de você.
Agora, a interface do usuário está fracamente acoplada a um objeto de dados. Porque é que está frouxamente acoplado em vez de firmemente acoplado? Devido à forma como as ligações são avaliadas. Cada controle tem uma BindingContext propriedade. 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 do objeto do contexto é verificada quanto às propriedades necessárias, como a associação do Text controle label à propriedade do Humidity contexto. Se Humidity não existir no contexto, nada acontece.
Como a interface de utilizador é fracamente acoplada, pode-se reprojetar a interface de utilizador sem se preocupar em quebrar o código. No entanto, você pode interromper a funcionalidade. Por exemplo, pode excluir o botão e a aplicação ainda compila e corre, mas não há forma de atualizar o clima. Por outro lado, você pode substituir os Entry controles 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, o uso da vinculação de dados no design da interface do usuário pode ajudá-lo 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.