パフォーマンスの最適化:データ バインディングOptimizing Performance: Data Binding

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) データ バインディングは、データを表示したり操作するための単純で一貫した方法をアプリケーションに提供します。data binding provides a simple and consistent way for applications to present and interact with data. 要素は、CLR オブジェクトおよびXMLXMLの形式で、さまざまなデータソースのデータにバインドできます。Elements can be bound to data from a variety of data sources in the form of CLR objects and XMLXML.

このトピックでは、データ バインディングのパフォーマンスに関する推奨事項について説明します。This topic provides data binding performance recommendations.

データ バインディングの参照が解決されるしくみHow Data Binding References are Resolved

データ バインディングのパフォーマンスの問題に入る前に、Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) のデータ バインディング エンジンがバインディングのオブジェクト参照をどのように解決するのかを説明します。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.

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)データバインディングのソースには、任意の CLR オブジェクトを指定できます。The source of a Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding can be any CLR object. CLR オブジェクトのプロパティ、サブプロパティ、またはインデクサーにバインドできます。You can bind to properties, sub-properties, or indexers of a CLR object. バインディング参照は Microsoft .NET Framework リフレクションまたはICustomTypeDescriptorのいずれかを使用して解決されます。The binding references are resolved by using either Microsoft .NET Framework reflection or an ICustomTypeDescriptor. 次に、バインディングのオブジェクト参照を解決するための 3 つの方法について説明します。Here are three methods for resolving object references for binding.

1 つ目は、リフレクションを使用する方法です。The first method involves using reflection. この場合、 PropertyInfoオブジェクトを使用してプロパティの属性を検出し、プロパティのメタデータにアクセスできるようにします。In this case, the PropertyInfo object is used to discover the attributes of the property and provides access to property metadata. ICustomTypeDescriptorインターフェイスを使用する場合、データバインディングエンジンは、このインターフェイスを使用してプロパティ値にアクセスします。When using the ICustomTypeDescriptor interface, the data binding engine uses this interface to access the property values. ICustomTypeDescriptorインターフェイスは、オブジェクトにプロパティの静的なセットがない場合に特に便利です。The ICustomTypeDescriptor interface is especially useful in cases where the object does not have a static set of properties.

プロパティの変更通知を提供するには、 INotifyPropertyChangedインターフェイスを実装するか、 TypeDescriptorに関連付けられている変更通知を使用します。Property change notifications can be provided either by implementing the INotifyPropertyChanged interface or by using the change notifications associated with the TypeDescriptor. ただし、プロパティ変更通知を実装する場合は、を使用INotifyPropertyChangedすることをお勧めします。However, the preferred strategy for implementing property change notifications is to use INotifyPropertyChanged.

ソースオブジェクトが clr オブジェクトで、source プロパティが clr プロパティの場合、 Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)データバインディングエンジンは、まず、 TypeDescriptorソースオブジェクトに対してリフレクションを使用してを取得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. パフォーマンスの観点から見た場合、このリフレクション操作のシーケンスには非常に時間がかかる可能性があります。This sequence of reflection operations is potentially very time-consuming from a performance perspective.

オブジェクト参照を解決する2番目の方法では、 INotifyPropertyChangedインターフェイスを実装する clr ソースオブジェクトと、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 this case, the data binding engine uses reflection directly on the source type and gets the required property. この方法も最適な方法とは言えませんが、最初の方法よりは作業セットの要件の負荷が小さくなります。This is still not the optimal method, but it will cost less in working set requirements than the first method.

オブジェクト参照を解決する3番目の方法では、 DependencyObjectソースオブジェクトがで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 this case, the data binding engine does not need to use reflection. 代わりに、プロパティ エンジンとデータ バインディング エンジンが連携してプロパティ参照を個別に解決します。Instead, the property engine and the data binding engine together resolve the property reference independently. これが、データ バインディングに使用されているオブジェクト参照を解決するための最適な方法です。This is the optimal method for resolving object references used for data binding.

次の表では、これら3つのText方法を使用TextBlockして、1000要素のプロパティをバインドするデータの速度を比較しています。The table below compares the speed of data binding the Text property of one thousand TextBlock elements using these three methods.

TextBlock の Text プロパティのバインド先Binding the Text property of a TextBlock バインディング時間 (ミリ秒)Binding time (ms) レンダリング時間 -- バインディングを含む (ミリ秒)Render time -- includes binding (ms)
CLR オブジェクトのプロパティへのTo a property of a CLR object 115115 314314
を実装する CLR オブジェクトのプロパティへのINotifyPropertyChangedTo a property of a CLR object which implements INotifyPropertyChanged 115115 305305
DependencyPropertyDependencyObjectに対する。To a DependencyProperty of a DependencyObject. 9090 263263

大きな CLR オブジェクトへのバインディングBinding to Large CLR Objects

1つの CLR オブジェクトに何千ものプロパティを使用してデータをバインドすると、パフォーマンスに大きな影響があります。There is a significant performance impact when you data bind to a single CLR object with thousands of properties. この影響を最小限に抑えるには、1つのオブジェクトを複数の CLR オブジェクトに分割し、プロパティを減らします。You can minimize this impact by dividing the single object into multiple CLR objects with fewer properties. この表は、1つの大きな CLR オブジェクト、または複数の小さいオブジェクトにデータをバインドするためのバインドとレンダリング時間を示しています。The table shows the binding and rendering times for data binding to a single large CLR object versus multiple smaller objects.

1000 個の TextBlock オブジェクトのデータ バインディングのバインド先Data binding 1000 TextBlock objects バインディング時間 (ミリ秒)Binding time (ms) レンダリング時間 -- バインディングを含む (ミリ秒)Render time -- includes binding (ms)
1000プロパティを持つ CLR オブジェクトTo a CLR object with 1000 properties 950950 12001200
1つのプロパティを持つ 1000 CLR オブジェクトTo 1000 CLR objects with one property 115115 314314

ItemsSource へのバインディングBinding to an ItemsSource

に表示する従業員の一覧を保持するList<T> CLR オブジェクトがあるシナリオについて考えてみます。ListBoxConsider 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. これら2つListBoxのオブジェクト間の対応を作成するには、従業員リストをItemsSourceのプロパティにバインドします。To create a correspondence between these two objects, you would bind your employee list to the ItemsSource property of the ListBox. ここで、グループに新しい従業員が加わったとします。However, suppose you have a new employee joining your group. この新しい人をバインドListBoxされた値に挿入するには、この人を従業員リストに追加するだけで、この変更がデータバインディングエンジンによって自動的に認識されることが期待できます。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. この想定は偽であることを前提としています。実際には、変更はListBox自動的にに反映されません。That assumption would prove false; in actuality, the change will not be reflected in the ListBox automatically. これは、CLR List<T>オブジェクトがコレクションの変更イベントを自動的に生成しないためです。This is because the CLR List<T> object does not automatically raise a collection changed event. で変更を取得ListBoxするには、従業員のリストを再作成し、のItemsSource 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. この解決方法で問題は解決されますが、パフォーマンスへの影響はきわめて大きくなります。While this solution works, it introduces a huge performance impact. ItemsSourceListBoxを新しいオブジェクトに再割り当てするたびに、最初に前の項目が破棄され、リスト全体が再生成されます。 ListBoxEach time you reassign the ItemsSource of ListBox to a new object, the ListBox first throws away its previous items and regenerates its entire list. が複雑ListBox DataTemplateなにマップされると、パフォーマンスへの影響が拡大されます。The performance impact is magnified if your ListBox maps to a complex DataTemplate.

この問題の非常に効率的な解決策は、従業員リストObservableCollection<T>をにすることです。A very efficient solution to this problem is to make your employee list an ObservableCollection<T>. オブジェクトObservableCollection<T>は、データバインディングエンジンが受け取ることができる変更通知を発生させます。An ObservableCollection<T> object raises a change notification which the data binding engine can receive. イベントは、リスト全体を再生成するItemsControl必要なく、から項目を追加または削除します。The event adds or removes an item from an ItemsControl without the need to regenerate the entire list.

次の表は、 ListBox 1 つの項目が追加されたときに (UI 仮想化がオフになっている) を更新するためにかかる時間を示しています。The table below shows the time it takes to update the ListBox (with UI virtualization turned off) when one item is added. 最初の行の数値は、CLR List<T>オブジェクトが要素のItemsSourceListBoxバインドされている場合の経過時間を表します。The number in the first row represents the elapsed time when the CLR List<T> object is bound to ListBox element's ItemsSource. 2番目の行の数値は、 ObservableCollection<T>ListBox要素のItemsSourceにバインドされている場合の経過時間を表します。The number in the second row represents the elapsed time when an ObservableCollection<T> is bound to the ListBox element's ItemsSource. ObservableCollection<T>データバインディング戦略を使用して時間を大幅に節約できることに注意してください。Note the significant time savings using the ObservableCollection<T> data binding strategy.

ItemsSource のデータ バインディングのバインド先Data binding the ItemsSource 1 項目の更新時間 (ミリ秒)Update time for 1 item (ms)
CLR List<T>オブジェクトへのTo a CLR List<T> object 16561656
ObservableCollection<T>To an ObservableCollection<T> 2020

IEnumerable ではなく IList を ItemsControl にバインドするBind IList to ItemsControl not IEnumerable

またはをItemsControl IList<T>オブジェクトにバインドするかどうかを選択できる場合は、オブジェクトを選択します。 IEnumerable IList<T>If you have a choice between binding an IList<T> or an IEnumerable to an ItemsControl object, choose the IList<T> object. をにIEnumerable バインドしてIList<T>ラッパーオブジェクトを作成します。これは、2番目のオブジェクトの不要なオーバーヘッドによってパフォーマンスが影響を受けることを意味します。 WPFWPF ItemsControlBinding 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.

データ バインディングのためだけに CLR オブジェクトを XML に変換しないDo not Convert CLR objects to XML Just for Data Binding.

WPFWPFコンテンツへのデータバインドを可能にします。ただし、 XMLXMLコンテンツへのデータバインディングは、CLR オブジェクトへのデータバインドよりも低速です。 XMLXMLallows you to data bind to XMLXML content; however, data binding to XMLXML content is slower than data binding to CLR objects. 唯一の目的がデータバインディング用である場合は、CLR オブジェクトデータを XML に変換しないでください。Do not convert CLR object data to XML if the only purpose is for data binding.

関連項目See also