WPF: какой самый эффективный/быстрый способ добавления элементов в ListView?

Мне нужно отобразить много строк в сетке, добавленной на довольно высокой частоте (до 10 строк в секунду в некоторых случаях) Я выбрал ListView, потому что я предполагаю, что это самый быстрый элемент управления сеткой в ​​WPF. (конечно, намного быстрее, чем GridView)

Загрузка процессора становится довольно высокой после того, как добавлено несколько сотен тысяч элементов, и они продолжают появляться. Это довольно удивительно, поскольку ListView отображает только видимые строки, поэтому не имеет значения, сколько из них добавлено.

Мой первый подход привязывал его к ObservableCollection, но через некоторое время загрузка процессора возрастает, и все окно становится нервным.

Чем я пытался связать его с обычным списком, который, как представляется, быстрее, однако мне нужно часто вызывать .Refresh() в списке, который через некоторое время также захлопывает процессор.

Чем я попытался подклассифицировать ObservableCollection, чтобы добавить фрагменты в надежде, что их пакетная обработка повысит производительность/снижение рабочей нагрузки процессора, но для этого подхода требуется вызов CollectionView.Refresh, который является так же, как вызов Reset() в коллекции, а также неопределенный, когда в коллекции много элементов.

Удаление наблюдаемого коллекций и вызов myListView.Items.Refresh(), чтобы вернуть его обратно в 0, возвращает cpu обратно в исходную точку.

Теперь у меня заканчиваются идеи. Опять же, моя цель здесь состоит в том, чтобы добавить/отобразить множество элементов и отобразить 8 столбцов, наиболее эффективным образом. ListView кажется хорошим, просто нужно быть каким-то образом я мог бы еще больше настроить его.

UPDATE

после профилирования строк ObservableCollection 800k в сетке наибольшая интенсивность работы cpu выполняется с помощью:

  • (75%) System.Windows.Media.MediaContext.RenderMessageHandler(объект resizedCompositionTarget)
  • (20%) ObservableCollection.OnCollectionChanged(NotifyCoolectionChanged..)

хотя в зависимости от сеанса эти цифры сильно различаются.

ОБНОВЛЕНИЕ 2.. ok. BindingList выглядит как явный победитель здесь.

Вот результаты (в тиках) бок о бок с 1 миллионом строк каждый (и добавление 10 пунктов в секунду):

ObservableCollection: http://i.imgur.com/7ZoSv.png

BindingList http://i.imgur.com/jm5qF.png

вы можете увидеть общее падение активности процессора и примерно половину тиков, необходимых для обработки дерева в случае списка привязок! Я благодарю Акаша за эту замечательную идею.

Ответы

Ответ 1

Вместо использования ObservableCollection я предлагаю класс BindingList, вы можете сделать что-то вроде этого.

BindingList<string> list = new BindingList<string>();

list.AllowEdit = true;
list.AllowNew = true;
list.AllowRemove = true;

// set the list as items source
itemCollection.ItemsSource = list;

// add many items...

// disable UI updation
list.RaiseListChangedEvents = false;

for each(string s in MyCollection){
   list.Add(s);
}

// after all.. update the UI with following
list.RaiseListChangedEvents = true;
list.ResetBindings(); // this forces update of entire list

Вы можете включать/отключать обновление даже в партиях, вместо того, чтобы добавлять все за один снимок, BindingList работает лучше, чем ObservableCollection во всем моем пользовательском интерфейсе, мне интересно, почему везде люди больше говорят о ObservableCollection, когда BindingList действительно вытесняет ObservableCollection.