WPF - VirtualizingStackPanel запрашивает все элементы при переходе в режим редактирования в DataGrid

Я использую DataGrid с CellEditingTemplates, Как ItemsSource используется виртуализированная коллекция данных (решение AlphaChiTech), которая по запросу извлекает только страницы размером 100 единиц одновременно.

Он прекрасно работает до тех пор, пока ячейка не будет дважды нажата в форме редактирования, затем VirtualizingStackPanel запрашивает все элементы один за другим. Конечно, в качестве побочного эффекта все страницы запрашиваются в конце концов.

Есть ли способ обойти эту проблему?

Редактировать:

Я нашел обходной путь, который может помочь людям в моей ситуации:

В конце концов я заметил, что VirtualizingStackPanel не запрашивает все элементы при условии, что высота строки остается неизменной после перехода в форму редактирования. До обхода проблемы моя форма редактирования была немного выше.

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

К сожалению, это работает только при определенных условиях. Есть случаи, в которых это не будет работать:

  • С помощью RowDetailsTemplate, Как только это видно, виртуализация нарушается. Я предполагаю, что детали строки принадлежат самой строке, поэтому высота строки снова увеличивается.

  • Вызов события Reset of the Collection соответственно CollectionView. По моему опыту, это вообще убийца виртуализации данных с DataGrids,

  • Уничтожая Count коллекции (это также не вызывает событие Reset).

Интересно, что увеличение Count из коллекции действительно работал. Но мне пришлось расширить возможности AlphaChiTech (к счастью, источники на github), потому что там нет никакого способа изменить Count без поднятия события Reset из коробки (по крайней мере, я не нашел). Так же DataGrid's элементы должны быть обновлены сразу же после этого, иначе будет выдано исключение о том, что ItemsControl и у коллекции есть несоответствующее состояние.

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

1 ответ

Решение

Обходной путь

Я нашел решение этой проблемы самостоятельно. Это временное решение предназначено для использования редактируемых коллекций с виртуализацией данных в WPF (виртуализированная коллекция только для чтения данных может быть реализована без обходных путей).

Во-первых, ряды должны быть одинаковыми. Одна из моих проблем заключалась в том, что CellEditingTemplates были выше, чем CellTemplates, Таким образом, каждый раз, когда форма редактирования была запущена, DataGrid достал все предметы коллекции. Настройка MinHeight из CellTemplates чтобы соответствовать высоте CellEditingTemplates сделал трюк.

По-видимому, RowDetailsTemplate принадлежат строке, поэтому, когда она становится видимой, она изменяет высоту строки и, следовательно, нарушает виртуализацию данных. Таким образом, может быть лучше пойти без подробностей строки и использовать шаблон основной детали, где "детали" отображаются за пределами DataGrid, Позже я пытаюсь реализовать это прямо сейчас (не полностью реализованная первая попытка сработала достаточно хорошо, чтобы сказать, что это не создает никаких проблем). Мне пришло в голову одно исключение для деталей строки: если детали строки всегда видны и каждый элемент имеет детали строки одинакового размера, то это может сработать. Идея заключалась бы в том, что высота строк тогда была бы одинаковой, но, поскольку в моем приложении только несколько элементов из всей коллекции нуждаются в деталях, я не пробовал этот подход.

Во-вторых, уменьшение количества - то есть, чтобы удалить элементы - и сброс элементов по коллекции или DataGrid вызвал также получение всех предметов. Обходной путь здесь заключается в замене существующей коллекции новым объектом коллекции из тех же элементов всякий раз, когда элемент добавляется или удаляется. К счастью, эта новая коллекция также виртуализирована с данными. Так что он все еще эффективен во времени, беглый и пользователь не заметит этого. Но по-прежнему существует проблема, если такое "обновление" выполняется, когда элемент выбран в DataGrid, Здесь приходит неприятный обходной путь: я реализовал два события в ViewModel, который управляет виртуальной коллекцией. Это PreVirtualizedRefresh а также PostVirtualizedRefresh, View с DataGrid подписывается на них и отменяет выбор каждого элемента в DataGrid на PreVirtualizedRefresh и на PostVirtualizedRefresh индекс отмененного выбора (если он запомнен) может быть выбран снова. Позже один все еще не работает для меня.

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

замечания

Из всех решений для виртуализации, которые я пробовал при решении этих проблем, я считаю, что решение AlphaChi является лучшим.

WPF определенно не предназначен для виртуализации данных. Его преемник UWP, с другой стороны, даже имеет собственный интерфейс для виртуализации данных. Поскольку у меня нет ни одного проекта UWP, я не мог бы попробовать сам, но я думаю, это было бы очень весело. Тем не менее, UWP не имеет родной DataGridТаким образом, виртуализированные данные коллекции должны быть переданы Lists или сторонний DataGrids, Таким образом, здесь также необходим компромисс.

Другие вопросы по тегам