Ottimizzazione delle prestazioni: associazione datiOptimizing Performance: Data Binding

Il data binding di Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) rappresenta per le applicazioni un modo semplice e coerente di presentare i dati e interagire con essi.Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding provides a simple and consistent way for applications to present and interact with data. Gli elementi possono essere associati a dati da un'ampia gamma di origini dati sotto forma di oggetti CLR e XML.Elements can be bound to data from a variety of data sources in the form of CLR objects and XML.

Questo argomento offre utili suggerimenti sulle prestazioni del data binding.This topic provides data binding performance recommendations.

Risoluzione dei riferimenti di data bindingHow Data Binding References are Resolved

Prima di trattare i problemi di prestazioni del data binding, è opportuno scoprire come vengono risolti dal motore di data binding di Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) i riferimenti agli oggetti per il binding.Before discussing data binding performance issues, it is worthwhile to explore how the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding engine resolves object references for binding.

L'origine di un Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding può essere qualsiasi oggetto CLR.The source of a Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding can be any CLR object. È possibile eseguire l'associazione a proprietà, sottoproprietà o indicizzatori di un oggetto CLR.You can bind to properties, sub-properties, or indexers of a CLR object. I riferimenti di associazione vengono risolti tramite Microsoft .NET Reflection del Framework o una ICustomTypeDescriptor.The binding references are resolved by using either Microsoft .NET Framework reflection or an ICustomTypeDescriptor. Di seguito vengono descritti i tre metodi disponibili per risolvere riferimenti a oggetti per il data binding.Here are three methods for resolving object references for binding.

Il primo metodo prevede l'uso della reflection.The first method involves using reflection. In questo caso, l'oggetto PropertyInfo viene usato per individuare gli attributi della proprietà e fornisce l'accesso ai metadati della proprietà.In this case, the PropertyInfo object is used to discover the attributes of the property and provides access to property metadata. Quando si usa l'interfaccia ICustomTypeDescriptor, il motore di data binding usa questa interfaccia per accedere ai valori delle proprietà.When using the ICustomTypeDescriptor interface, the data binding engine uses this interface to access the property values. L'interfaccia ICustomTypeDescriptor è particolarmente utile nei casi in cui l'oggetto non dispone di un set statico di proprietà.The ICustomTypeDescriptor interface is especially useful in cases where the object does not have a static set of properties.

Le notifiche di modifica delle proprietà possono essere fornite implementando l'interfaccia INotifyPropertyChanged o utilizzando le notifiche di modifica associate al TypeDescriptor.Property change notifications can be provided either by implementing the INotifyPropertyChanged interface or by using the change notifications associated with the TypeDescriptor. Tuttavia, la strategia consigliata per l'implementazione delle notifiche delle modifiche delle proprietà consiste nell'utilizzare INotifyPropertyChanged.However, the preferred strategy for implementing property change notifications is to use INotifyPropertyChanged.

Se l'oggetto di origine è un oggetto CLR e la proprietà di origine è una proprietà CLR, il motore di Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding deve innanzitutto utilizzare la reflection sull'oggetto di origine per ottenere il TypeDescriptor, quindi eseguire una query per una PropertyDescriptor.If the source object is a CLR object and the source property is a CLR property, the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding engine has to first use reflection on the source object to get the TypeDescriptor, and then query for a PropertyDescriptor. Questa sequenza di operazioni di reflection richiede potenzialmente molto tempo da un punto di vista delle prestazioni.This sequence of reflection operations is potentially very time-consuming from a performance perspective.

Il secondo metodo per la risoluzione dei riferimenti a oggetti comporta un oggetto di origine CLR che implementa l'interfaccia INotifyPropertyChanged e una proprietà di origine che è una proprietà CLR.The second method for resolving object references involves a CLR source object that implements the INotifyPropertyChanged interface, and a source property that is a CLR property. In questo caso, il motore di data binding usa direttamente la reflection sul tipo di origine e ottiene la proprietà necessaria.In this case, the data binding engine uses reflection directly on the source type and gets the required property. Sebbene presenti requisiti del working set inferiori rispetto al primo metodo, non si tratta ancora del metodo ottimale.This is still not the optimal method, but it will cost less in working set requirements than the first method.

Il terzo metodo per la risoluzione dei riferimenti a oggetti prevede l'uso di un oggetto di origine che è un DependencyObject e una proprietà di origine DependencyProperty.The third method for resolving object references involves a source object that is a DependencyObject and a source property that is a DependencyProperty. In questo caso, non è necessario che il motore di data binding usi la reflection:In this case, the data binding engine does not need to use reflection. il motore della proprietà e il motore di data binding risolvono il riferimento alla proprietà in modo indipendente.Instead, the property engine and the data binding engine together resolve the property reference independently. Si tratta del metodo ottimale per la risoluzione dei riferimenti a oggetti usati per il data binding.This is the optimal method for resolving object references used for data binding.

Nella tabella seguente viene confrontata la velocità di data binding la proprietà Text di elementi TextBlock 1000 usando questi tre metodi.The table below compares the speed of data binding the Text property of one thousand TextBlock elements using these three methods.

Binding della proprietà Text di un TextBlockBinding the Text property of a TextBlock Tempo di binding (ms)Binding time (ms) Tempo di rendering: include il binding (ms)Render time -- includes binding (ms)
A una proprietà di un oggetto CLRTo a property of a CLR object 115115 314314
A una proprietà di un oggetto CLR che implementa INotifyPropertyChangedTo a property of a CLR object which implements INotifyPropertyChanged 115115 305305
A un DependencyProperty di un DependencyObject.To a DependencyProperty of a DependencyObject. 9090 263263

Binding a oggetti CLR di grandi dimensioniBinding to Large CLR Objects

Quando si esegue l'associazione dati a un singolo oggetto CLR con migliaia di proprietà, si verifica un notevole impatto sulle prestazioni.There is a significant performance impact when you data bind to a single CLR object with thousands of properties. È possibile ridurre questo effetto dividendo il singolo oggetto in più oggetti CLR con un minor numero di proprietà.You can minimize this impact by dividing the single object into multiple CLR objects with fewer properties. La tabella mostra i tempi di binding e di rendering per data binding a un singolo oggetto CLR di grandi dimensioni rispetto a più oggetti più piccoli.The table shows the binding and rendering times for data binding to a single large CLR object versus multiple smaller objects.

Data binding di 1000 oggetti TextBlockData binding 1000 TextBlock objects Tempo di binding (ms)Binding time (ms) Tempo di rendering: include il binding (ms)Render time -- includes binding (ms)
A un oggetto CLR con proprietà 1000To a CLR object with 1000 properties 950950 12001200
Per 1000 oggetti CLR con una proprietàTo 1000 CLR objects with one property 115115 314314

Binding a una proprietà ItemsSourceBinding to an ItemsSource

Si consideri uno scenario in cui è presente un oggetto List<T> CLR che contiene un elenco di dipendenti che si desidera visualizzare in una ListBox.Consider a scenario in which you have a CLR List<T> object that holds a list of employees that you want to display in a ListBox. Per creare una corrispondenza tra questi due oggetti, è necessario associare l'elenco dei dipendenti alla proprietà ItemsSource della ListBox.To create a correspondence between these two objects, you would bind your employee list to the ItemsSource property of the ListBox. Si supponga ora che un nuovo dipendente si unisca al gruppo.However, suppose you have a new employee joining your group. Si potrebbe pensare che, per inserire questo nuovo utente nei valori ListBox associati, è sufficiente aggiungere tale persona all'elenco dei dipendenti e prevedere che questa modifica venga riconosciuta automaticamente dal motore di data binding.You might think that in order to insert this new person into your bound ListBox values, you would simply add this person to your employee list and expect this change to be recognized by the data binding engine automatically. Tale presupposto risulterebbe false; in realtà, la modifica non verrà riflessa automaticamente nel ListBox.That assumption would prove false; in actuality, the change will not be reflected in the ListBox automatically. Questo è dovuto al fatto che l'oggetto List<T> CLR non genera automaticamente un evento di modifica della raccolta.This is because the CLR List<T> object does not automatically raise a collection changed event. Per fare in modo che il ListBox rilevi le modifiche, è necessario ricreare l'elenco dei dipendenti e ricollegarlo alla proprietà ItemsSource dell'ListBox.In order to get the ListBox to pick up the changes, you would have to recreate your list of employees and re-attach it to the ItemsSource property of the ListBox. Questa soluzione funziona, ma incide considerevolmente sulle prestazioni.While this solution works, it introduces a huge performance impact. Ogni volta che si riassegna la ItemsSource di ListBox a un nuovo oggetto, il ListBox prima di tutto genera gli elementi precedenti e rigenera l'intero elenco.Each time you reassign the ItemsSource of ListBox to a new object, the ListBox first throws away its previous items and regenerates its entire list. L'effetto sulle prestazioni viene ingrandito se il ListBox viene mappato a un DataTemplatecomplesso.The performance impact is magnified if your ListBox maps to a complex DataTemplate.

Una soluzione molto efficiente per questo problema consiste nel fare in modo che il dipendente elenchi un ObservableCollection<T>.A very efficient solution to this problem is to make your employee list an ObservableCollection<T>. Un oggetto ObservableCollection<T> genera una notifica di modifica che può essere ricevuta dal motore di data binding.An ObservableCollection<T> object raises a change notification which the data binding engine can receive. L'evento aggiunge o rimuove un elemento da un ItemsControl senza la necessità di rigenerare l'intero elenco.The event adds or removes an item from an ItemsControl without the need to regenerate the entire list.

La tabella seguente mostra il tempo necessario per aggiornare la ListBox (con la virtualizzazione dell'interfaccia utente disattivata) quando viene aggiunto un elemento.The table below shows the time it takes to update the ListBox (with UI virtualization turned off) when one item is added. Il numero nella prima riga rappresenta il tempo trascorso quando l'oggetto CLR List<T> viene associato al ItemsSourcedi ListBox elemento.The number in the first row represents the elapsed time when the CLR List<T> object is bound to ListBox element's ItemsSource. Il numero nella seconda riga rappresenta il tempo trascorso quando un ObservableCollection<T> viene associato al ItemsSourcedell'elemento del ListBox.The number in the second row represents the elapsed time when an ObservableCollection<T> is bound to the ListBox element's ItemsSource. Si noti il notevole risparmio di tempo con la strategia di data binding ObservableCollection<T>.Note the significant time savings using the ObservableCollection<T> data binding strategy.

Data binding della proprietà ItemsSourceData binding the ItemsSource Tempo di aggiornamento per 1 elemento (ms)Update time for 1 item (ms)
A un oggetto List<T> CLRTo a CLR List<T> object 16561656
A un ObservableCollection<T>To an ObservableCollection<T> 2020

Binding di IList a ItemsControl non IEnumerableBind IList to ItemsControl not IEnumerable

Se è possibile scegliere tra associare un IList<T> o un IEnumerable a un oggetto ItemsControl, scegliere l'oggetto IList<T>.If you have a choice between binding an IList<T> or an IEnumerable to an ItemsControl object, choose the IList<T> object. Il binding IEnumerable a un ItemsControl impone WPFWPF di creare un wrapper IList<T> oggetto, il che significa che le prestazioni sono influenzate dal sovraccarico superfluo di un secondo oggetto.Binding IEnumerable to an ItemsControl forces WPFWPF to create a wrapper IList<T> object, which means your performance is impacted by the unnecessary overhead of a second object.

Non convertire oggetti CLR in XML solo per il data bindingDo not Convert CLR objects to XML Just for Data Binding.

WPFWPF consente di associare dati al contenuto XML; Tuttavia, data binding al contenuto XML è più lento rispetto data binding agli oggetti CLR.allows you to data bind to XML content; however, data binding to XML content is slower than data binding to CLR objects. Non convertire i dati dell'oggetto CLR in XML se l'unico scopo è data binding.Do not convert CLR object data to XML if the only purpose is for data binding.

Vedere ancheSee also