Comparer une interface utilisateur pilotée par les événements à une interface utilisateur liée aux données
- 6 minutes
Une interface utilisateur pilotée par les événements est conçue autour des événements exposés par un contrôle. Ces événements peuvent être associés au code du gestionnaire d’événements appelé lorsque l’événement est déclenché. Par exemple, supposons que vous disposez d’un bouton qui, lorsque vous cliquez dessus, effectue une opération longue. Le gestionnaire d’événements affecté à l’événement Clicked peut démarrer l’opération, puis définir la propriété IsEnabled du bouton sur false, empêchant ainsi l’utilisateur de cliquer à nouveau sur le bouton pendant l’exécution de l’opération.
Une interface utilisateur liée aux données utilise la liaison de données pour présenter des données et interagir avec elles. Les propriétés des contrôles sont liées aux propriétés de l’objet de données, et ces liaisons peuvent détecter les modifications apportées aux propriétés. Revenons au bouton qui effectue une opération de longue durée dans l’exemple précédent. Au lieu de désactiver le bouton dans le code-behind, nous lions la propriété IsEnabled à la propriété IsBusy de l’objet de données. Chaque fois que l’objet de données devient « occupé », l’état activé du bouton est automatiquement modifié pour correspondre.
Avantages et inconvénients de l’utilisation d’événements et du code-behind
L’utilisation du gestionnaire d’événements du contrôle avec du code-behind est un moyen rapide et pratique de concevoir la logique d’application pour votre interface utilisateur. Vous utilisez du code pour appeler des services pour obtenir des données, effectuer des opérations sur ces données et interagir avec les contrôles de la page. Le code est utilisé pour synchroniser l’interface utilisateur et les données.
Prenons l’exemple d’une application de service météo. Le fragment XAML suivant contient un bouton d’interface utilisateur simple que l’utilisateur sélectionne pour obtenir les dernières données et mettre à jour l’interface utilisateur avec l’humidité.
<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>
Cet exemple comprend trois contrôles nommés :
- Contrôle
Entrynommé PostalCode. - Contrôle
Buttonnommé RefreshWeatherButton. - Contrôle nommé « Humidity »
Label.
RefreshWeatherButton possède un gestionnaire d’événements déclaré pour l’événement Clicked. Lorsque le bouton est cliqué, le gestionnaire d’événements interroge un service météo pour connaître les dernières prévisions météorologiques à l’aide des données entrées dans le contrôle d’entrée et définit le texte de l’étiquette PostalCodeHumidity sur l’humidité actuelle.
private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
WeatherService.Location = PostalCode.Text;
WeatherService.Refresh();
Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}
Dans ce gestionnaire d’événement unique, trois contrôles sont étroitement couplés les uns aux autres et aux données par le biais du code-behind.
Cette conception fonctionne très bien pour les petites interfaces utilisateur, mais dès que l'interface devient plus complexe, la gestion d'un code étroitement lié peut poser problème. Si vous supprimez ou modifiez un contrôle, vous devez nettoyer tout le code utilisant ces contrôles d’interface utilisateur (ce qui peut inclure le gestionnaire d’événements). Si vous décidez de redéfinir l’interface utilisateur, vous aurez également beaucoup de code à refactoriser. Et lorsque la structure de données de stockage change, vous devez vous plonger dans le code de chaque interface utilisateur pour que tout reste synchronisé.
La liaison de données simplifie les choses
Vous pouvez implémenter des liaisons de données en XAML ou du code, mais elles sont beaucoup plus courantes en XAML, où elles aident à réduire la taille du fichier code-behind. Lorsque vous remplacez le code procédural dans les gestionnaires d’événements par du code déclaratif ou du balisage, l’application est simplifiée et précise. Étant donné que les liaisons ne nécessitent pas de code-behind, vous pouvez facilement créer, modifier ou redéfinir l’interface utilisateur pour l’adapter à la façon dont vous souhaitez présenter les données.
Prenons le même exemple que dans la section précédente, mais mettons-le à jour pour utiliser la liaison de données :
<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>
Vous pouvez repérer les propriétés liées aux données, celles-ci utilisant la syntaxe d’extension XAML {Binding ...} pour la valeur de la propriété. Ne vous inquiétez pas encore des spécificités ; nous abordons cela plus loin dans ce module.
Les trois mêmes contrôles sont déclarés dans le code XAML, mais aucun d’entre eux n’est nommé, car un nom n’est pas obligatoire :
Entrycontrôle : la propriété deTextce contrôle est liée à une propriété nomméeLocation.Buttoncontrôle : la propriété duCommandbouton est liée à une propriété nomméeRefreshWeather.Commandest une propriété sur le bouton qui appelle du code lorsque l’utilisateur appuie sur le bouton. Il s’agit d’une méthode alternative à l’utilisation de l’événementClickeddans la liaison de données.Labelcontrol : cetteTextpropriété est liée à une propriété nomméeHumidity.
Dans cette interface utilisateur simple, tout le code sous-jacent est éliminé. Supprimer tout le code-behind n’est pas le but de la liaison de données, même si c’est possible. Le code-behind a toujours sa place. C’est à vous de décider dans quelle mesure vous souhaitez implémenter la liaison de données.
À présent, l’interface utilisateur est faiblement couplée à un objet de données. Pourquoi est-elle faiblement couplée et non étroitement couplée ? Cela est dû à la façon dont les liaisons sont évaluées. Chaque contrôle possède une propriété BindingContext. Si le contexte n’est pas défini, le contexte du contrôle parent est utilisé, et ainsi de suite jusqu’à ce que la racine du XAML soit évaluée. Lorsque les liaisons sont évaluées, l’instance d’objet du contexte est vérifiée pour déterminer si les propriétés requises existent, comme la liaison Text du contrôle d’étiquette à la propriété Humidity du contexte. Si Humidity n’existe pas sur le contexte, rien ne se passe.
L’interface utilisateur étant faiblement couplée, vous pouvez la reconcevoir sans risquer que le code ne fonctionne plus correctement. Toutefois, vous pouvez affecter le fonctionnement de l’application. Par exemple, si vous supprimez le bouton, l’application se compile et s’exécute toujours, mais vous n’avez aucun moyen d’actualiser la météo. D’un autre côté, vous pouvez remplacer les contrôles Entry et Button par le contrôle SearchBar unique. Ce contrôle vous permet d’entrer du texte et d’appeler une commande.
<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />
Comme vous pouvez le voir, l’utilisation de la liaison de données dans la conception de votre interface utilisateur peut vous aider à faire évoluer et à modifier votre interface utilisateur sans trop de travail. L’interface utilisateur est synchronisée automatiquement avec les données, et la logique de l’application est séparée de l’interface utilisateur.