Optimisation des performances : liaison de données

La liaison de données Windows Presentation Foundation (WPF) offre un moyen simple et cohérent pour les applications de présenter et d’interagir avec les données. Les éléments peuvent être liés à des données provenant de diverses sources de données sous la forme d’objets CLR et XML.

Cette rubrique fournit des recommandations sur les performances de la liaison de données.

Comment les références de liaison de données sont résolues

Avant de discuter des problèmes de performances de liaison de données, il est utile d’explorer comment le moteur de liaison de données WPF (Windows Presentation Foundation) résout les références d’objets pour la liaison.

La source d’une liaison de données WPF (Windows Presentation Foundation) peut être n’importe quel objet CLR. Vous pouvez lier des propriétés, des sous-propriétés ou des indexeurs d’un objet CLR. Les références de liaison sont résolues à l’aide de la réflexion Microsoft .NET Framework ou d’un ICustomTypeDescriptor. Voici trois méthodes permettant de résoudre les références d’objet pour la liaison.

La première méthode repose sur l’utilisation de la réflexion. Dans ce cas, l’objet PropertyInfo est utilisé pour découvrir les attributs de la propriété et fournit l’accès aux métadonnées de propriété. Lorsque vous utilisez l’interface ICustomTypeDescriptor , le moteur de liaison de données utilise cette interface pour accéder aux valeurs de propriété. L’interface ICustomTypeDescriptor est particulièrement utile dans les cas où l’objet n’a pas d’ensemble statique de propriétés.

Les notifications de modification de propriété peuvent être fournies en implémentant l’interface INotifyPropertyChanged ou en utilisant les notifications de modification associées au TypeDescriptor. Toutefois, la stratégie recommandée pour l’implémentation des notifications de modification de propriété consiste à utiliser INotifyPropertyChanged.

Si l’objet source est un objet CLR et que la propriété source est une propriété CLR, le moteur de liaison de données WPF (Windows Presentation Foundation) doit d’abord utiliser la réflexion sur l’objet source pour obtenir , TypeDescriptorpuis rechercher un PropertyDescriptor. Cette séquence d’opérations de réflexion peut s’avérer très fastidieuse du point de vue des performances.

La deuxième méthode de résolution des références d’objet implique un objet source CLR qui implémente l’interface INotifyPropertyChanged et une propriété source qui est une propriété CLR. Dans ce cas, le moteur de liaison de données applique la réflexion directement au type de source et obtient la propriété nécessaire. Ce n’est toujours pas la méthode optimale, mais elle est moins exigeante que la première méthode en termes de spécifications de la plage de travail.

La troisième méthode de résolution des références d’objet implique un objet source qui est une DependencyObject propriété source qui est un DependencyProperty. Dans ce cas, le moteur de liaison de données n’a pas besoin d’utiliser la réflexion. Au lieu de cela, le moteur de propriété et le moteur de liaison de données résolvent ensemble la référence de propriété de manière indépendante. Il s’agit de la méthode optimale pour résoudre les références d’objet utilisées pour la liaison de données.

Le tableau ci-dessous compare la vitesse de liaison de données à la Text propriété d’un millier TextBlock d’éléments à l’aide de ces trois méthodes.

Liaison de la propriété Text d’un TextBlox Temps de liaison (ms) Temps de rendu -- liaison incluse (ms)
À une propriété d’un objet CLR 115 314
À une propriété d’un objet CLR qui implémente INotifyPropertyChanged 115 305
À un DependencyProperty d’un DependencyObject. 90 263

Liaison à des objets CLR volumineux

Il existe un impact significatif sur les performances lorsque vous liez des données à un seul objet CLR avec des milliers de propriétés. Vous pouvez réduire cet impact en divisant l’objet unique en plusieurs objets CLR avec moins de propriétés. Le tableau affiche les heures de liaison et de rendu pour la liaison de données à un seul objet CLR volumineux par rapport à plusieurs objets plus petits.

Liaison de données de 1 000 objets TextBlock Temps de liaison (ms) Temps de rendu -- liaison incluse (ms)
Vers un objet CLR avec 1 000 propriétés 950 1200
À 1 000 objets CLR avec une propriété 115 314

Liaison à un ItemsSource

Considérez un scénario dans lequel vous avez un objet CLR List<T> qui contient une liste d’employés que vous souhaitez afficher dans un ListBox. Pour créer une correspondance entre ces deux objets, vous devez lier votre liste d’employés à la ItemsSource propriété du ListBox. Or, il se trouve qu’un nouvel employé rejoint le groupe. Vous pouvez penser que pour insérer cette nouvelle personne dans vos valeurs liées ListBox , vous devez simplement ajouter cette personne à votre liste des employés et vous attendre à ce que cette modification soit reconnue automatiquement par le moteur de liaison de données. Cette hypothèse s’avérerait fausse ; en réalité, la modification ne sera pas reflétée automatiquement ListBox . Cela est dû au fait que l’objet CLR List<T> ne déclenche pas automatiquement un événement modifié de collection. Pour récupérer ListBox les modifications, vous devrez recréer votre liste d’employés et le rattacher à nouveau à la ItemsSource propriété du ListBox. Bien que cette solution fonctionne, elle a un fort impact sur les performances. Chaque fois que vous réaffectez l’objet ItemsSourceListBox à un nouvel objet, le ListBox premier lève ses éléments précédents et régénère toute sa liste. L’impact sur les performances est agrandi si vos ListBox mappages à un complexe DataTemplate.

Une solution très efficace à ce problème consiste à faire de votre liste des employés un ObservableCollection<T>. Un ObservableCollection<T> objet déclenche une notification de modification que le moteur de liaison de données peut recevoir. L’événement ajoute ou supprime un élément d’un ItemsControl élément sans avoir à régénérer toute la liste.

Le tableau ci-dessous indique le temps nécessaire à la mise à jour (avec la virtualisation de l’interface ListBox utilisateur désactivée) lorsqu’un élément est ajouté. Le nombre de la première ligne représente le temps écoulé lorsque l’objet CLR List<T> est lié à ListBox l’élément ItemsSource. Le nombre de la deuxième ligne représente le temps écoulé lorsqu’un ObservableCollection<T> élément est lié à l’élément ItemsSourceListBox . Notez les économies significatives de temps à l’aide de la stratégie de ObservableCollection<T> liaison de données.

Liaison de données de la propriété ItemsSource Temps de mise à jour pour 1 élément (ms)
Vers un objet CLR List<T> 1 656
Vers un ObservableCollection<T> 20

Lier un objet IList à un objet ItemsControl non IEnumerable

Si vous avez le choix entre lier un IList<T> ou IEnumerable un ItemsControl objet, choisissez l’objet IList<T> . La liaison IEnumerable à un ItemsControl WPF force à créer un objet wrapper IList<T> , ce qui signifie que vos performances sont affectées par la surcharge inutile d’un deuxième objet.

Ne convertissez pas des objets CLR en XML seulement à des fins de liaison de données.

WPF vous permet de lier des données au contenu XML ; Toutefois, la liaison de données au contenu XML est plus lente que la liaison de données aux objets CLR. Ne convertissez pas les données d’objet CLR en XML si la seule finalité est la liaison de données.

Voir aussi