Оптимизация производительности: привязка данных

Привязка данных Windows Presentation Foundation (WPF) обеспечивает простой и согласованный способ представления данных и взаимодействия с ними в приложениях. Можно связывать элементы с данными из разнообразных источников данных в форме объектов CLR и XML.

В этом разделе содержатся рекомендации по оптимизации производительности привязки данных.

В этом разделе содержатся следующие подразделы.

  • Как разрешаются ссылки для привязки данных
  • Привязка к большим объектам среды CLR
  • Привязка к ItemsSource
  • Связывание IList с ItemsControl не является IEnumerable
  • Не следует преобразовывать объекты среды CLR в XML только для связывания данных.
  • Связанные разделы

Как разрешаются ссылки для привязки данных

Прежде чем обсуждать вопросы производительности привязки данных, стоит рассмотреть, как ядро связывания данных Windows Presentation Foundation (WPF) разрешает ссылки на объекты для привязки.

Источником привязки данных Windows Presentation Foundation (WPF) может быть любой объект CLR. Можно выполнять привязку к свойствам, подсвойствам или индексаторам объекта CLR. Ссылки привязки разрешаются с помощью отражения Microsoft .NET Framework или ICustomTypeDescriptor. Существуют три метода для разрешения ссылок на объекты для привязки:

Первый метод включает использование отражения. В этом случае объект PropertyInfo используется для просмотра атрибутов свойства и обеспечивает доступ к метаданным свойства. При использовании интерфейса ICustomTypeDescriptor, ядро привязки данных использует этот интерфейс для доступа к значениям свойств. Интерфейс ICustomTypeDescriptor является особенно полезным в случае, когда объект не имеет постоянного набора свойств.

Свойство уведомления об изменениях может быть предоставлено с помощью реализации интерфейса INotifyPropertyChanged, либо с помощью уведомлений об изменениях, связанных с TypeDescriptor. Однако основной стратегией использования уведомлений об изменениях свойств является использование INotifyPropertyChanged.

Если исходным объектом является объект CLR, а исходным свойством является свойство CLR, ядро привязки данных Windows Presentation Foundation (WPF) должно сначала использовать отражение для исходного объекта, чтобы получить TypeDescriptor, а затем запросить PropertyDescriptor. Эта последовательность операций отражения потенциально занимает очень много времени с точки зрения производительности.

Второй метод разрешения ссылок на объекты включает исходный объект CLR, реализующий интерфейс INotifyPropertyChanged и исходное свойство, которое является свойством CLR. В этом случае ядро привязки данных использует отражение непосредственно для исходного типа и возвращает необходимое свойство. Это не самый оптимальный метод, но он менее трудозатратный, чем первый метод.

Третий метод для разрешения ссылок на объекты включает исходный объект DependencyObject и исходное свойство DependencyProperty. В этом случае для использования отражения ядро привязки данных не требуется. Вместо этого свойство ядра и ядро привязки данных независимо друг от друга разрешают ссылку на свойство. Это оптимальный метод для разрешения ссылок на объекты, используемые для привязки данных.

Ниже в таблице сравнивается скорость привязки данных свойства Text для одной тысячи TextBlock элементов с помощью этих трех методов.

Связывание свойства Text элемента TextBlock

Время привязки (мс)

Время отображения — включает привязку (мс)

К свойству объекта CLR

115

314

К свойству объекта CLR, который реализует INotifyPropertyChanged

115

305

К DependencyProperty для DependencyObject.

90

263

Привязка к большим объектам среды CLR

Привязка данных к одному объекту CLR с тысячами свойств значительно влияет на производительность. Это влияние можно минимизировать путем деления одного объекта на несколько объектов CLR с меньшим количеством свойств. В таблице показана привязка и время отрисовки при связывании данных с одним большим объектом CLR и несколькими небольшими объектами.

Привязка данных к 1000 объектов TextBlock

Время привязки (мс)

Время отображения — включает привязку (мс)

К объекту CLR с 1 000 свойств

950

1200

К 1 000 объектов CLR с одним свойством

115

314

Привязка к ItemsSource

Рассмотрим сценарий, в котором имеется объект CLR List<T>, содержащий список сотрудников, который требуется отобразить в ListBox. Чтобы установить соответствие между этими двумя объектами, можно привязать список сотрудников к свойству ItemsSource для ListBox. Предположим, к группе присоединяется новый сотрудник. Может показаться, что чтобы вставить этого человека в список связанных значений ListBox, нужно просто добавить его в список сотрудников и ожидать, что это изменение автоматически распознается ядром привязки данных. Это предположение оказалось бы ложным. В действительности изменения не будут отражаться в ListBox автоматически. Это происходит потому, что объект CLR List<T> не вызывает автоматически измененное событие коллекции. Чтобы изменения отражались в ListBox, необходимо повторно создать список сотрудников и присоединить его к свойству ItemsSource для ListBox. Данное решение оказывает существенное воздействие на производительность. Каждый раз при присваивании ItemsSource для ListBox новому объекту ListBox сначала отбрасывает предыдущие элементы, а потом заново создает весь список. Влияние на производительность усиливается, если ListBox сопоставляется со сложным DataTemplate.

Эффективным решением этой проблемы является преобразование списка сотрудников в ObservableCollection<T>. Объект ObservableCollection<T> вызывает уведомление об изменении, которое может получать ядро привязки данных. Событие добавляет или удаляет элемент из ItemsControl без необходимости восстановления всего списка.

В нижеприведенной таблице показано время, необходимое для обновления ListBox (с отключенной виртуализацией пользовательского интерфейса) при добавлении элемента. Число в первой строке представляет собой затраченное время, когда объект CLR List<T> привязывается к ItemsSource элемента ListBox. Число во второй строке представляет собой затраченное время, когда ObservableCollection<T> привязывается к ItemsSource элемента ListBox. Обратите внимание на экономию времени, полученную от использования стратегии привязки данных ObservableCollection<T>.

Привязка данных к ItemsSource

Время обновления для 1 элемента (мс)

К объекту List<T> в CLR.

1656

К ObservableCollection<T>

20

Связывание IList с ItemsControl не является IEnumerable

Если имеется выбор между привязкой IList<T> или IEnumerable к объекту ItemsControl, следует выбрать объект IList<T>. Привязка IEnumerable к ItemsControl приводит к тому, что WPF создает обертку объекта IList<T>, что означает ненужную нагрузку на производительность от второго объекта.

Не следует преобразовывать объекты среды CLR в XML только для связывания данных.

WPF позволяет связать данные с содержимым XML. Привязка к содержимому XML выполняется медленнее, чем привязка данных к объектам CLR. Не следует преобразовывать данные объекта CLR в XML только для связывания данных.

См. также

Задачи

Пошаговое руководство. Кэширование данных приложения WPF

Основные понятия

Улучшение производительности приложений WPF

Планирование производительности приложения

Оптимизация производительности. Использование преимуществ аппаратного ускорения

Оптимизация производительности: разметка и разработка

Оптимизация производительности: двумерная графика и обработка изображений

Оптимизация производительности: поведение объекта

Оптимизация производительности: ресурсы приложения

Оптимизация производительности: отображение текста

Оптимизация производительности. Дополнительные рекомендации

Общие сведения о связывании данных