ProgrammationDéveloppeur VB.NET / Développeur Desktop

Comment les collections de type ObservableCollection sont-elles mises en œuvre et utilisées dans Visual Basic, dans quels cas sont-elles préférables à d'autres collections, et comment garantir la notification correcte des modifications des éléments pour fonctionner avec le binding de données ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique du sujet

Avec l'évolution de la plateforme .NET, Visual Basic a introduit des collections avancées telles que ObservableCollection(Of T). Cette collection est conçue pour notifier l'interface utilisateur (UI) des changements de données, ce qui est particulièrement important lors de l'utilisation du binding de données (data binding) — par exemple, dans WPF ou WinForms avec le support du modèle MVVM. Les constructions plus anciennes comme List(Of T) ou ArrayList ne supportaient pas la notification automatique des changements et nécessitaient une refonte manuelle de la logique d'affichage.

Problème

Les collections ordinaires ne notifient pas l'interface ou les objets abonnés de leurs propres modifications — ajout, suppression, réarrangement des éléments. En conséquence, les contrôles UI (par exemple, listes, tableaux) ne se mettent pas à jour automatiquement et nécessitent un redessin ou des appels de méthode supplémentaires pour actualiser. Cette synchronisation manuelle entraîne des erreurs et complique la logique du code.

Solution

ObservableCollection(Of T) implémente l'interface INotifyCollectionChanged, ce qui permet à l'UI d'être automatiquement informée de tout ajout, suppression ou modification d'éléments. Pour une mise à jour complète des données lors de la modification des objets eux-mêmes dans la collection, il est recommandé que les éléments stockés implémentent également l'interface INotifyPropertyChanged.

Exemple de code :

Imports System.Collections.ObjectModel Imports System.ComponentModel Public Class Item Implements INotifyPropertyChanged Private _name As String Public Property Name As String Get Return _name End Get Set(value As String) If _name <> value Then _name = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name")) End If End Set End Property Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged End Class Dim items As New ObservableCollection(Of Item)() AddHandler items.CollectionChanged, Sub(s, e) Console.WriteLine($"Action: {e.Action}") End Sub items.Add(New Item() With {.Name = "Test 1"}) items(0).Name = "Updated Name"

Caractéristiques clés :

  • La collection notifie les abonnés de l'ajout, de la suppression, du déplacement et du nettoyage
  • Lors de la modification des propriétés des objets dans la collection, le support de INotifyPropertyChanged est requis pour une synchronisation automatique avec l'UI
  • Utilisé pour le binding aux modèles UI dans WPF, où les changements sont reflétés sans code supplémentaire

Questions pièges.

ObservableCollection peut-elle notifier les changements de propriétés des éléments si l'élément change mais que la collection elle-même (composition, taille) ne change pas ?

Non, par défaut, ObservableCollection ne suit que les changements de la collection elle-même, et non les propriétés des éléments individuels. Pour refléter les changements de propriétés dans l'UI, les objets doivent implémenter l'interface INotifyPropertyChanged, et le binding dans l'UI doit prendre cela en charge.

Les notifications de changement se produiront-elles si la collection est modifiée en dehors du thread de l'UI ?

Non, les modifications de la collection en dehors du thread principal (UI) entraîneront une erreur ou un comportement incorrect dans certains frameworks (par exemple, WPF). Pour les modifications multithread, il est nécessaire d'utiliser Dispatcher.Invoke ou des analogues pour que la synchronisation se produise dans le bon thread.

Peut-on utiliser ObservableCollection pour le binding dans WinForms ou cela fonctionne-t-il uniquement dans WPF ?

ObservableCollection fonctionne également dans WinForms, cependant dans WinForms, une synchronisation manuelle et une mise à jour des données sont nécessaires, car le binding standard de cette plateforme ne reconnaît pas toujours les événements de la collection. Dans WPF, l'implémentation est maximisée sans couture.

Erreurs typiques et anti-patterns

  • Utiliser ObservableCollection, mais les éléments qu'elle contient ne réalisent pas INotifyPropertyChanged, donc l'UI ne se met pas à jour lors de changements de propriétés
  • Modification de la collection à partir d'un mauvais thread (non-UI)
  • Remplacez l'ensemble de la collection plutôt que de mettre à jour son contenu, ce qui casse le binding UI

Exemple de la vie

Cas négatif

Un programmeur crée une liste de produits pour l'interface, utilise une simple List(Of T), et après chaque ajout ou suppression d'éléments, il effectue manuellement des appels de méthodes pour mettre à jour l'UI. Parfois, il oublie de mettre à jour la liste ou ne calcule pas correctement les indices lors de la suppression d'éléments.

Avantages :

  • Plus simple à réaliser pour de très petits projets
  • Pas besoin d'étudier des événements et interfaces supplémentaires

Inconvénients :

  • L'UI est souvent désynchronisée avec les données réelles
  • Beaucoup d'erreurs manuelles et de code superflu
  • Le support devient plus compliqué à mesure que le projet grandit

Cas positif

ObservableCollection(Of T) est mise en œuvre et les objets prennent en charge INotifyPropertyChanged. Toutes les actions — ajout, suppression, modification — se reflètent automatiquement dans l'interface grâce au binding. La logique de l'UI passe à une réaction simplifiée, sans un grand nombre de mises à jour manuelles.

Avantages :

  • L'UI et les données sont toujours synchronisées
  • Minimum d'appels manuels aux contrôles
  • Facile à maintenir et à étendre

Inconvénients :

  • Il est nécessaire d'initialement prévoir le support des événements et des interfaces
  • Il faut résoudre les questions de synchronisation des threads dans des scénarios complexes