Шаблоны запросов строк DataGrid с виртуализацией данных
Я реализовал решение для виртуализации данных, используя некоторые идеи из CodePlex и блога статьи Bea Stollnitz и Vincent Da Ven Berhge (та же ссылка). Однако мне нужен был другой подход, поэтому я решил написать собственное решение.
Я использую DataGrid
чтобы отобразить около миллиона строк с этим решением. Я также использую виртуализацию пользовательского интерфейса. Мое решение выполнимо, но в некоторых ситуациях я наблюдаю странное поведение DataGrid
запрашивает данные из своего источника.
О решении
Я закончил тем, что написал список, который делает всю тяжелую работу. Это универсальный класс с именем VirtualList<T>.
Он реализует ICollectionViewFactory
интерфейс, поэтому механизм создания представления коллекции может создать VirtualListCollectionView<T>
экземпляр, чтобы обернуть его. Этот класс наследует от ListCollectionView
, Я не последовал советам, чтобы написать свой ICollectionView
реализация. Наследование, похоже, тоже работает нормально.
VirtualList<T>
разбивает все данные на страницы. Он получает общее количество предметов и каждый раз, когда DataGrid
запрашивает строку через индексатор списка, загружает соответствующую страницу или возвращает ее из кэша. Страницы переработаны внутри и DispatcherTimer
удаляет неиспользуемые страницы в простое.
Шаблоны запроса данных
Первое, что я узнал, что
VirtualList<T>
следует реализоватьIList
(не универсальный). В противном случаеItemsControl
будет рассматривать это какIEnumerable
и запросить / перечислить все строки. Это логично, так какDataGrid
не является безопасным типом, поэтому он не может использоватьIList<T>
интерфейс.Строка с индексом 0 часто задается
DataGrid
, Кажется, он используется для визуального измерения элемента (в соответствии со стеком вызовов). Итак, я просто кеширую это.Механизм кеширования внутри
DataGrid
использует предсказуемый шаблон для запроса строк, которые он показывает. Сначала он запрашивает видимые строки сверху вниз (два раза для каждой строки), затем он запрашивает пару строк (в зависимости от размера видимой области) перед видимой областью (включая первую видимую строку) в нисходящем порядке. порядок так, снизу вверх. После этого он запрашивает одинаковое количество строк после видимых строк (включая последнюю видимую строку) сверху вниз.Если видимые индексы строки 4,5,6. Запрос данных будет: 4,4,5,5,6,6,4,3,2,1,6,7,8,9.
Если размер моей страницы установлен правильно, я могу обслуживать все эти запросы с текущей и ранее загруженной страницы.
Если
CanSelectMultipleItems
являетсяTrue
и пользователь выбирает несколько элементов с помощью кнопки SHIFT или перетаскивания мышью,DataGrid
перечисляет все строки от начала списка до конца выделения. Это перечисление происходит черезIEnumerable
интерфейс независимо от тогоIList
реализовано или нет.Если выбранная строка не видна и текущая видимая область находится "далеко" от выбранной строки, иногда DataGrid начинает запрашивать все элементы, от выбранной строки до конца видимой области. Включая все строки между которыми даже не видны. Я не мог понять точную модель этого поведения. Может быть, моя реализация является причиной этого.
Мои вопросы
Мне интересно, почему
DataGrid
запросы на невидимые строки, так как эти строки будут запрашиваться снова, когда станут видимыми?Почему необходимо запрашивать каждую строку два или три раза?
Может кто-нибудь сказать мне, как заставить DataGrid не использовать
IEnumerable
кроме выключения выбора нескольких элементов?
1 ответ
Я, по крайней мере, нашел способ обмануть VirtualList. Вы можете прочитать это здесь.
Если вы нашли другое решение (это даже лучше, чем у меня), пожалуйста, сообщите мне!