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.