Шаблоны запросов строк 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. Вы можете прочитать это здесь.

Если вы нашли другое решение (это даже лучше, чем у меня), пожалуйста, сообщите мне!

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