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 la liaison de données, il est utile d’explorer comment le moteur de liaison de données Windows Presentation Foundation (WPF) 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'une méthode 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 la propriété. L’interface ICustomTypeDescriptor est particulièrement utile dans les cas où l’objet n’a pas un 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 le TypeDescriptor, puis 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 un DependencyObject et une 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 propriété Text d’un millier d’éléments TextBlock à l’aide de ces trois méthodes.
Liaison de la propriété Texte d’un TextBlox | Temps de liaison (ms) | Temps de rendu – inclut la liaison (ms) |
---|---|---|
À une propriété d’un objet CLR | 115 | 314 |
À une propriété d’un objet CLR qui implémente INotifyPropertyChanged | 115 | 305 |
Vers 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 – inclut la liaison (ms) |
---|---|---|
Vers un objet CLR avec 1 000 propriétés | 950 | 1200 |
À 1 000 objets CLR dotés d’une propriété | 115 | 314 |
Liaison à un ItemsSource
Considérez un scénario dans lequel vous avez un objet CLRList<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 propriété ItemsSource du ListBox. Or, il se trouve qu’un nouvel employé rejoint le groupe. Vous pouvez dès lors penser que pour insérer cette nouvelle personne dans vos valeurs ListBox liées, il vous suffit d’ajouter la personne à la liste d’employés et d’attendre 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 dans le ListBox. Cela est dû au fait que l’objet CLRList<T> ne déclenche pas automatiquement un événement modifié de collection. Pour que le ListBox prenne en compte les modifications, vous devrez recréer votre liste d’employés et la rattacher à la propriété ItemsSource du ListBox. Bien que cette solution fonctionne, elle a un fort impact sur les performances. Chaque fois que vous réaffectez le ItemsSource de ListBox à un nouvel objet, le ListBox jette d’abord ses éléments précédents et régénère toute sa liste. L’impact sur les performances est amplifié si votre ListBox est mappé à un DataTemplate complexe.
Une solution très efficace à ce problème consiste à faire de votre liste d’employés un ObservableCollection<T>. Un objet déclenche ObservableCollection<T> 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 sans avoir à régénérer toute la liste.
Le tableau ci-dessous indique le temps nécessaire à la mise à jour du ListBox (en ayant désactivé la virtualisation de l’interface utilisateur) quand un élément est ajouté. Le nombre de la première ligne représente le temps écoulé lorsque l’objet CLRList<T> est lié à la ItemsSourcede l’élément ListBox . Le nombre de la deuxième ligne représente le temps écoulé lorsqu’un ObservableCollection<T> est lié au ItemsSource de l’élément ListBox. Notez les économies significatives de temps à l’aide de la stratégie de liaison de données ObservableCollection<T>.
Liaison de données de la propriété ItemsSource | Temps de mise à jour pour 1 élément (ms) |
---|---|
Vers un objet CLRList<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 un IEnumerable à un objet ItemsControl, choisissez l’objet IList<T>. La liaison de IEnumerable à ItemsControl oblige WPF à créer un objet enveloppe IList<T>, ce qui signifie que vos performances sont affectées par la surcharge inutile d’un deuxième objet.
Ne pas convertir d’objets CLR en XML uniquement pour la 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 de liaison de données.
Voir aussi
- Optimisation des performances des applications WPF
- Planification de la performance applicative
- Tirer parti du matériel
- Disposition et conception
- Graphiques 2D et acquisition d'images
- Comportement de l’objet
- Ressources d'application
- Text
- Autres recommandations relatives aux performances
- Vue d’ensemble de la liaison de données
- Procédure pas à pas : mise en cache de données d’application dans une application WPF
.NET Desktop feedback