Comparar uma interface do usuário orientada a eventos com uma interface do usuário vinculada a dados
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 IsEnabled
propriedade é vinculada à propriedade do objeto de IsBusy
dados. 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 interface do usuário simples que o usuário seleciona para obter os dados mais recentes e atualizar a interface do usuário 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:
Entry
controle chamado PostalCode.Button
chamado RefreshWeatherButton.Label
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 PostalCode
no controle de entrada, e define o texto do Humidity
rótulo 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 são firmemente acoplados entre si e os 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, 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
As associações de dados podem ser implementadas em XAML ou código, mas são muito mais comuns em XAML, onde ajudam a reduzir o tamanho do arquivo code-behind. Ao substituir 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, que é abordado mais adiante neste módulo.
Os mesmos três controles são declarados no XAML, mas nenhum deles é nomeado, pois um nome não é necessário:
Entry
Controlo:A propriedade deste
Text
controle está vinculada a uma propriedade chamadaLocation
.Button
Controlo:A propriedade do
Command
botã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 aoClicked
evento usado na vinculação de dados.Label
Controlo:Esta
Text
propriedade está vinculada a uma propriedade chamadaHumidity
.
Nesta interface do usuário simples, todo o code-behind é eliminado. Remover todo o code-behind não é o ponto da vinculação de dados, embora geralmente 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 do usuário é fracamente acoplada, você pode reprojetar a interface do usuário sem a preocupação de quebrar o código. No entanto, você pode interromper a funcionalidade. Por exemplo, você pode excluir o botão e o aplicativo ainda compila e é executado, mas você não tem uma maneira de atualizar o tempo. 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.