Почему сортировка с использованием CollectionViewSource.SortDescription является медленной? - PullRequest
8 голосов
/ 28 октября 2009

Это метод сортировки по умолчанию, когда вы щелкаете заголовок столбца в DataGrid. Если базовый список содержит 100 000 элементов, обновление представления занимает около 20 секунд. Та же самая задержка может наблюдаться при установке SortDescription с на CollectionView.

Сортировка с использованием ListCollectionView.CustomSort или сортировка и повторное получение списка работает практически мгновенно.

Почему эта задержка? Является ли это просто «налогом на отражение» на связанные свойства?

Ответы [ 2 ]

9 голосов
/ 28 октября 2009

Вы правы, это налог на отражение. Некоторое время назад я очень внимательно посмотрел на производительность DataGrid, и рефлексия оказалась здесь узким местом. Независимо от того, насколько быстро работает алгоритм сортировки, они не кэшируют значение свойства между двумя сравнениями. Таким образом, даже если у вас n * ln (n) сравнений, при n == 100 000 вы получите ~ 1 000 000 операций. Каждый операнд использует отражение, чтобы получить значение, поэтому у вас есть 2 000 000 вызовов для отражения в налоге :) ... ListCollectionView.CustomSort является идеальным решением здесь.

PS: В конце концов, мы написали сетку на основе ListView, потому что нас тоже не устраивала производительность рендеринга DataGrid ... Но это уже другая история

1 голос
/ 15 марта 2012

Лучшей настройкой производительности для фильтрации было переключение DataGridRow Visibility. Это имело значение разницы!

1.Добавьте свойство IsVisible к элементу коллекции, с которым вы связываете ItemSrid объекта DataGrid.

private bool _isVisible = true;
public bool IsVisible
{
    get { return _isVisible; }
    set 
    { 
        if (_isVisible == value)
             return;
        _isVisible = value;
        RaisePropertyChanged(()=>IsVisible);
     }
 }

2. Запустите видимость DataGridRow, привязав его к свойству IsVisible:

<DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type DataGridRow}">
    <Setter Property="Visibility" 
                Value="{Binding Path=IsVisible, 
                                Converter={StaticResource BoolToVisibility}}"/>
 </Style>
</DataGrid.ItemContainerStyle>

3.Хорошо, вы должны установить IsVisible где-то, я думаю, тоже, как в вашей ViewModel. Вот только пример того, что я делаю (просто копирую / вставляю задание) - в основном устанавливаю IsVisible в true или false, основываясь на некоторых критериях в моей другой ViewModel:

FilterViewModel.OnFilter += (s, a) =>
{
    foreach (Row row in ViewModel.Rows)
    row.IsVisible = !FilterViewModel.FilteringItems.Any(item => 
                                   item.IsSelected && item.Name == row.Name);
};
...