Подтвердить что ты не робот

Шаблоны запросов строк 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, за исключением отключения выбора нескольких элементов?

4b9b3361

Ответ 1

Я хотя бы нашел способ обмануть VirtualList. Вы можете прочитать здесь.

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