Delen via


Prestaties optimaliseren: gegevensbinding

Windows Presentation Foundation -gegevensbinding (WPF) biedt een eenvoudige en consistente manier voor toepassingen om gegevens te presenteren en ermee te communiceren. Elementen kunnen worden gebonden aan gegevens uit verschillende gegevensbronnen in de vorm van CLR objecten en XML.

Dit onderwerp bevat aanbevelingen voor de prestaties van gegevensbindingen.

Hoe gegevensbindingsverwijzingen worden opgelost

Voordat u prestatieproblemen met gegevensbindingen bespreekt, is het de moeite waard om te ontdekken hoe de WPF-gegevensbindingengine (Windows Presentation Foundation) objectverwijzingen voor binding oplost.

De bron van een WPF-gegevensbinding (Windows Presentation Foundation) kan elk CLR object zijn. U kunt binden aan eigenschappen, subeigenschappen of indexeerfuncties van een CLR-object. De bindingsverwijzingen worden opgelost met behulp van Microsoft .NET Framework-reflectie of een ICustomTypeDescriptor. Hier volgen drie methoden voor het oplossen van objectverwijzingen voor binding.

De eerste methode omvat het gebruik van weerspiegeling. In dit geval wordt het PropertyInfo object gebruikt om de kenmerken van de eigenschap te detecteren en toegang te bieden tot metagegevens van eigenschappen. Wanneer u de ICustomTypeDescriptor-interface gebruikt, gebruikt de engine voor gegevensbinding deze interface om toegang te krijgen tot de eigenschapswaarden. De ICustomTypeDescriptor-interface is vooral handig in gevallen waarin het object geen statische set eigenschappen heeft.

Meldingen over het wijzigen van eigenschappen kunnen worden verstrekt door de INotifyPropertyChanged interface te implementeren of door de wijzigingsmeldingen te gebruiken die zijn gekoppeld aan de TypeDescriptor. De voorkeursstrategie voor het implementeren van meldingen voor het wijzigen van eigenschappen is echter het gebruik van INotifyPropertyChanged.

Als het bronobject een CLR-object is en de broneigenschap een CLR eigenschap is, moet de wpF-gegevensbindingsengine (Windows Presentation Foundation) eerst reflectie op het bronobject gebruiken om de TypeDescriptorop te halen en vervolgens een query uit te voeren op een PropertyDescriptor. Deze reeks weerspiegelingsbewerkingen is mogelijk zeer tijdrovend vanuit prestatieperspectief.

De tweede methode voor het omzetten van objectverwijzingen omvat een CLR bronobject dat de INotifyPropertyChanged-interface implementeert en een broneigenschap die een CLR eigenschap is. In dit geval gebruikt de gegevensbindingsengine reflectie direct op het brontype om de vereiste eigenschap te verkrijgen. Dit is nog steeds niet de optimale methode, maar het vereist minder resources in de werkset dan de eerste methode.

De derde methode voor het omzetten van objectverwijzingen omvat een bronobject dat een DependencyObject is en een broneigenschap die een DependencyPropertyis. In dit geval hoeft de engine voor gegevensbinding geen weerspiegeling te gebruiken. In plaats daarvan lossen de eigenschapsengine en de gegevensbindingsengine de eigenschapsreferentie afzonderlijk op. Dit is de optimale methode voor het omzetten van objectverwijzingen die worden gebruikt voor gegevensbinding.

In de onderstaande tabel wordt de snelheid vergeleken van de gegevensbinding van de eigenschap Text van duizend TextBlock elementen met behulp van deze drie methoden.

de eigenschap Text van een TextBlock- binden bindingstijd (ms) Render-tijd, inclusief binding (ms)
Naar een eigenschap van een CLR-object 115 314
Naar een eigenschap van een CLR-object dat INotifyPropertyChanged implementeert 115 305
Naar een DependencyProperty van een DependencyObject. 90 263

Binding met grote CLR-objecten

Er is een aanzienlijke invloed op de prestaties wanneer u gegevens verbindt met één CLR-object met duizenden eigenschappen. U kunt deze impact minimaliseren door het ene object te verdelen in meerdere CLR objecten met minder eigenschappen. In de tabel ziet u de bindings- en renderingtijden voor gegevensbinding met één groot CLR object versus meerdere kleinere objecten.

Gegevensbinding van 1000 TextBlock-objecten bindingstijd (ms) Render-tijd, inclusief binding (ms)
Naar een CLR-object met 1000 eigenschappen 950 1200
Naar 1000 CLR objecten met één eigenschap 115 314

Binding aan een ItemsSource

Overweeg een scenario waarin u een CLRList<T> object hebt met een lijst met werknemers die u wilt weergeven in een ListBox. Als u een correspondentie tussen deze twee objecten wilt maken, koppelt u uw werknemerslijst aan de eigenschap ItemsSource van de ListBox. Stel dat u een nieuwe werknemer hebt die deelneemt aan uw groep. Als u deze nieuwe persoon wilt invoegen in uw gebonden ListBox waarden, voegt u deze persoon gewoon toe aan uw werknemerslijst en verwacht u dat deze wijziging automatisch wordt herkend door de gegevensbindingsengine. Die aanname zou onwaar blijken; in werkelijkheid wordt de wijziging niet automatisch doorgevoerd in de ListBox. Dit komt doordat het CLRList<T> object niet automatisch een gewijzigde gebeurtenis voor een verzameling genereert. Om ervoor te zorgen dat de ListBox de wijzigingen oppikt, moet u de lijst met werknemers opnieuw maken en deze opnieuw koppelen aan de ItemsSource-eigenschap van de ListBox. Hoewel deze oplossing werkt, introduceert deze een enorme impact op de prestaties. Telkens wanneer u de ItemsSource van ListBox aan een nieuw object opnieuw toegeeft, gooit de ListBox eerst de vorige items weg en wordt de hele lijst opnieuw gegenereerd. De invloed op de prestaties wordt vergroot als uw ListBox wordt toegewezen aan een complex DataTemplate.

Een zeer efficiënte oplossing voor dit probleem is om uw werknemerslijst een ObservableCollection<T>te maken. Een ObservableCollection<T>-object genereert een wijzigingsmelding die de engine voor gegevensbinding kan ontvangen. Met de gebeurtenis wordt een item toegevoegd aan of verwijderd uit een ItemsControl zonder dat de hele lijst opnieuw hoeft te worden gegenereerd.

In de onderstaande tabel ziet u de tijd die nodig is om de ListBox bij te werken (waarbij UI-virtualisatie is uitgeschakeld) wanneer er één item wordt toegevoegd. Het getal in de eerste rij geeft de verstreken tijd aan wanneer het CLRList<T> object afhankelijk is van ListBox element ItemsSource. Het getal in de tweede rij geeft de verstreken tijd aan wanneer een ObservableCollection<T> is gebonden aan de ListBoxvan het ItemsSource element. Let op de aanzienlijke tijdbesparing met behulp van de ObservableCollection<T> strategie voor gegevensbinding.

Het koppelen van gegevens aan de ItemsSource Tijd bijwerken voor 1 item (ms)
Naar een CLRList<T>-object 1656
Naar een ObservableCollection<T> 20

IList binden aan ItemsControl niet IEnumerable

Als u een keuze hebt tussen het binden van een IList<T> of een IEnumerable aan een ItemsControl object, kiest u het IList<T> object. Door IEnumerable te binden aan een ItemsControl dwingt WPF om een wrapper IList<T>-object te maken, wat betekent dat uw prestaties worden beïnvloed door de onnodige overhead van een tweede object.

Converteer CLR objecten niet naar XML Just for Data Binding.

MET WPF kunt u gegevens binden aan XML-inhoud; Gegevensbinding naar XML-inhoud is echter langzamer dan gegevensbinding met CLR objecten. Converteer CLR objectgegevens niet naar XML als het enige doel is voor gegevensbinding.

Zie ook