Проблемы производительности при прокрутке WPG Toolkit DataGrid - почему? - PullRequest
24 голосов
/ 10 ноября 2009

У меня проблема с производительностью (WPF Toolkit) DataGrid. Он содержит около 1000 строк (только восемь столбцов), а прокрутка ужасно медленная и медленная. Также начальная загрузка окна, содержащего DataGrid, занимает 5-10 секунд.

Я провел некоторые исследования (с использованием Google и StackOverflow), но не смог найти ничего, кроме рекомендации включить виртуализацию пользовательского интерфейса. Но даже после явного включения прокрутка продолжает работать очень медленно.

Моя DataGrid связана с ICollectionView / CollectionViewSource. Это определяется в XAML следующим образом (столбцы определены явно, а не генерируются автоматически):

    <tk:DataGrid x:Name="dataGrid" 
                 ItemsSource="{Binding Path=Bookings}" 
                 AutoGenerateColumns="False" 
                 Grid.Row="1" 
                 EnableRowVirtualization="True" 
                 EnableColumnVirtualization="True"
                 VirtualizingStackPanel.IsVirtualizing="True"
                 VirtualizingStackPanel.VirtualizationMode="Recycling">
            ... 
    </tk:DataGrid>

Для DataContext для всего окна задан экземпляр класса, содержащего ICollectionView, с которым связан DataGrid.

Каждый найденный мною блог или форум хвалил производительность DataGrid, поэтому я совершенно очевидно что-то серьезно ошибаюсь. Поскольку я довольно новичок в WPF в целом и особенно в DataGrid, я понятия не имею, как это улучшить. У кого-нибудь есть какой-нибудь совет для меня? Какой у вас опыт работы с DataGrid? Что я делаю не так?

Редактировать: Только что следовал совету этого вопроса, чтобы установить для ширины всех столбцов значение "Авто". Это не изменило плохую производительность прокрутки. Также я не использую DataGridTemplateColumns (только некоторые DataGridTextColumns и две DataGridComboBoxColumns).

Edit2: я использовал Snoop, чтобы посмотреть на мое приложение. То, что я вижу, говорит о том, что виртуализация действительно работает (всего 19 строк, а не тысяча). Но каждая строка содержит 52 элемента, так что они составляют более тысячи элементов. Может ли это быть / проблема?

Большое спасибо!

Ответы [ 7 ]

19 голосов
/ 16 июня 2012

DataGrid имеет свойство Attached, ScrollViewer.CanContentScroll , которое управляет этим поведением. Чтобы получить плавную прокрутку, вам нужно установить False .

6 голосов
/ 09 августа 2011

После того, как я наконец-то нашел время для сборки приложения на основе новейшей версии WPF, проблема с прокруткой, похоже, полностью исчезла. Поэтому, если кто-то еще использует версию инструментария DataGrid, просто «обновите» до версии, включенной в платформу, и все будет в порядке.

4 голосов
/ 05 октября 2011

Я использую .NET 4.0 и все еще получаю проблему с производительностью прокрутки. Что я сделал - отключил виртуализацию. Я установил EnableRowVirtualization на «ложь» в DataGrid. Это значительно улучшило производительность прокрутки.

Я бы предложил не предполагать, что то, что предлагает WPF, полезно во всех ситуациях.

3 голосов
/ 10 ноября 2009

В каком контейнере находится ваша сетка данных? Например, если вы поместите его в средство просмотра прокрутки, сетка данных будет расти для отображения каждой строки, таким образом, эффективно отключая виртуализацию (и программа прокрутки сделает ее нормальной, пока это происходит). Убедитесь, что размер сетки данных ограничен.

Это действительно звучит как виртализация, если этот совет не работает, запустите ваше приложение через профилировщик, чтобы убедиться, что виртуализация происходит.

Редактировать: Вот пример того, как использовать snoop (или, я думаю, крота), чтобы быстро увидеть, работает ли виртуализация. http://blogs.msdn.com/jgoldb/archive/2008/03/25/quick-tips-to-improve-wpf-app-memory-footprint.aspx

2 голосов
/ 08 декабря 2010

Что касается начальной загрузки, я обнаружил, что необходимо расширять публичный API, чтобы значительно улучшить большое количество загрузок столбцов - мы говорим от минут до секунды. Тем не менее, у меня есть похожие проблемы с производительностью прокрутки, даже более 500 столбцов прокручивается очень медленно.

Установка столбцов в моей производной сетке данных:

var columns = new DataGridColumnCollection(true, dataGrid);
        for (int i = 0; i < pivotTable.DetailsColumnCount; i++)
        {
            if (!pivotTable.NullColumns.Contains(i))
            {
                columns.Add(new PivotDetailColumn(pivotTable, i));
            }
        }
        columns.ForceUpdate();

        dataGrid.Columns = columns;

        dataGrid.ItemsSource =
            Enumerable.Range(0, pivotTable.DetailsRowCount)
                .Where(i => !pivotTable.NullRows.Contains(i)) // Only non null rows
                .ToList();

Исправления для DataGridColumnCollection:

public class DataGridColumnCollection : ObservableCollection<DataGridColumn>
{
    private bool _DeferColumnChangeUpdates = false;

    public DataGridColumnCollection(bool deferColumnChangeUpdates, DataGrid dataGridOwner)
        : this(dataGridOwner)
    {
        _DeferColumnChangeUpdates = deferColumnChangeUpdates;
    }

    public DataGridColumnCollection(DataGrid dataGridOwner)
    {
        Debug.Assert(dataGridOwner != null, "We should have a valid DataGrid");

        DisplayIndexMap = new List<int>(5);
        _dataGridOwner = dataGridOwner;

        RealizedColumnsBlockListForNonVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForNonVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForNonVirtualizedRows = true;

        RealizedColumnsBlockListForVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForVirtualizedRows = true;
    }

    #region Protected Overrides

    public void ForceUpdate()
    {
        if (DisplayIndexMapInitialized)
        {
            UpdateDisplayIndexForNewColumns(this, 0);
        }

        InvalidateHasVisibleStarColumns();
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
            if (!_DeferColumnChangeUpdates)
            {
                if (DisplayIndexMapInitialized)
                {
                    UpdateDisplayIndexForNewColumns(e.NewItems, e.NewStartingIndex);
                }

                InvalidateHasVisibleStarColumns();
            }
                break;
2 голосов
/ 14 октября 2010

Вы можете попробовать добавить элементы по одному (или по строкам) в сетку данных и обновлять поток пользовательского интерфейса после каждого добавления. Таким образом, пользователь видит, как происходит загрузка, и не похоже, что приложение ничего не делает. Смотрите здесь более подробное описание этого метода

0 голосов
/ 18 июня 2019

Я обнаружил, что при установке ширины столбца на Auto (по умолчанию!) Может возникнуть значительная задержка вертикальной прокрутки, когда имеется много ячеек. Переключение на фиксированную ширину очень помогло в моем случае, хотя при наличии большого количества столбцов все еще наблюдается определенная задержка.

Вы можете установить CanUserResizeColumns="True" в сетке, если вы беспокоитесь, что пользователям не понравятся выбранные вами ширины.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...