WPF DataGrid: свойство CanContentScroll, вызывающее нечетное поведение

У меня есть решение, в котором я генерирую DataGrid (или несколько экземпляров) на основе пользовательских критериев. Каждая grid продолжает получать данные, когда она приходит через ObservableCollection

проблема, которую я имел, заключалась в том, что свиток действовал странно. Это было изменчиво, и полоса прокрутки изменила бы ее размеры при прокрутке.

чем я нашел .. CanContentScroll свойство! Он полностью фиксирует странное поведение прокрутки, приносящее мне временное блаженство и счастье.

однако он вызывает 2 неудачных побочных эффекта.

  1. всякий раз, когда я снова создаю экземпляры сетки и привязываю их к моей наблюдаемой коллекции, она замораживает все мое окно в течение 5 секунд. когда моя grid растет до большого размера, эта задержка может продолжаться 30 секунд.

  2. когда я вызываю TradeGrid.ScrollIntoView (TradeGrid.Items (TradeGrid.Items.Count – 1)), чтобы прокручивать его вниз, он прыгает снизу вверх и назад.

есть ли другой способ добиться плавной прокрутки?

Вы сталкиваетесь с различиями между физической прокруткой и логической прокруткой.

Как вы обнаружили, у каждого есть свои компромиссы.

Физическая прокрутка

Физическая прокрутка (CanContentScroll = false) просто идет по пикселям, поэтому:

  • Окно просмотра всегда представляет собой ту же часть вашего размера прокрутки, что дает вам гладкий опыт прокрутки и

но

  • Все содержимое DataGrid должно иметь все шаблоны, полностью примененные и измеренные и упорядоченные, чтобы определить размер полосы прокрутки, что приводит к длительным задержкам во время загрузки и высокой оперативной памяти, и
  • Он действительно не прокручивает элементы, поэтому он не очень хорошо разбирается в ScrollIntoView

Логическая прокрутка

Логическая прокрутка (CanContentScroll = true) вычисляет его видовое окно прокрутки и степень по элементам вместо пикселей, поэтому:

  • В окне просмотра может отображаться различное количество элементов в разное время, то есть количество элементов в окне просмотра по сравнению с количеством элементов в пределах варьируется, что приводит к изменению длины полосы прокрутки и

  • Прокрутка перемещается от одного элемента к другому и никогда между ними, что приводит к «отрывистой» прокрутке

но

  • Пока вы используете VirtualizingStackPanel под капотом, нужно только применять шаблоны, а также измерять и упорядочивать элементы, которые на самом деле видны на данный момент, и

  • ScrollIntoView намного проще, так как нужно просто получить нужный индекс элемента

Выбор между ними

Это только два вида прокрутки, предоставляемые WPF. Вы должны выбирать между ними на основе вышеупомянутых компромиссов. Обычно логическая прокрутка лучше всего подходит для средних и больших наборов данных, а физическая прокрутка лучше всего подходит для небольших.

Трюк для ускорения загрузки во время физической прокрутки состоит в том, чтобы сделать физическую прокрутку лучше, чтобы обернуть ваши предметы в пользовательский Decorator, который имеет фиксированный размер и устанавливает видимость своего ребенка в скрытое, когда он невидим. Это предотвращает появление ApplyTemplate, Measure и Arrange на элементах управления потомками этого элемента, пока вы не будете готовы к этому.

Трюк, чтобы сделать ScrollIntoView для физической прокрутки более надежным, – это вызвать его дважды: сразу же и один раз в обратном вызове диспетчера DispatcherPriority.ApplicationIdle.

Создание стабильной полосы прокрутки логического прокрутки

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

Также возможно изменить поведение самого ScrollBar, поэтому большой палец всегда рассчитывается как фиксированный размер. Чтобы сделать это без какого-либо взломанного кода:

  • Subclass Track, чтобы заменить вычисление положения и размера Thumb в MeasureOverride с помощью собственного
  • Измените шаблон ScrollBar, используемый для прокрутки ScrollBar с логической прокруткой, чтобы использовать ваш подclassовый трек вместо обычного
  • Измените шаблон ScrollViewer, чтобы явно установить свой собственный шаблон ScrollBar на ScrollBar с логической прокруткой (вместо использования шаблона по умолчанию)
  • Измените шаблон ListBox, чтобы использовать явно установленный пользовательский шаблон ScrollViewer на ScrollViewer, который он создает.

Это означает, что вы копируете много шаблонов кода с встроенными шаблонами WPF, поэтому это не очень изящное решение. Но альтернативой этому является использование хакерского кода для ожидания до тех пор, пока все шаблоны не будут расширены, а затем найдите ScrollBar и просто замените шаблон ScrollBar тем, который использует ваш собственный трек. Этот код сохраняет два больших шаблона (ListBox, ScrollViewer) за счет очень сложного кода.

Использование другой панели будет гораздо большим объемом работы: VirtualizingStackPanel – это единственная панель, которая виртуализирует, и только она и StackPanel для логической прокрутки. Поскольку вы пользуетесь возможностями виртуализации VirtualizingStackPanel, вам придется повторно реализовать все эти функции, а также все функции информации IScrollInfo и ваши обычные функции Panel. Я мог бы сделать что-то подобное, но я бы выделил несколько, возможно, много дней, чтобы все было правильно. Я рекомендую вам не попробовать.

У меня также есть проблема с моей DataGrid, и, наконец, я сделал:

ScrollViewer.CanContentScroll="True" EnableRowVirtualization="True" VirtualizingPanel.VirtualizationMode="Standard" 

Теперь все отлично работает в моем DataGrid.

  • Свяжите элемент с двумя источниками
  • Ранняя и поздняя привязка
  • Загрузка файлов с Java-клиента на HTTP-сервер
  • WPF StringFormat на содержании ярлыков
  • Связывающие элементыСвойства ComboBoxColumn в WPF DataGrid
  • Ошибка WPF: не удается найти управляющий элемент FrameworkElement для целевого элемента
  • WPF StringFormat = {0: C}, показывающий как доллары
  • Связывание в текстовом столбце таблицы данных WPF
  • Связывание WPF DataGrid с DataTable с использованием TemplateColumns
  • ComboBox.SelectedValue не обновляется из источника привязки
  • Как вы привязываете CollectionContainer к коллекции в модели представления?
  • Interesting Posts

    Как извлечь 7z zip и иметь правильную структуру директории?

    Как отключить встроенную клавиатуру моего ноутбука в Windows 7?

    Удалить атрибут C # свойства динамически

    Как запустить программу при подключении к определенной сети в Windows 7

    Найти мой собственный идентификатор процесса в VBScript

    Понимание .AsEnumerable () в LINQ to SQL

    Как заставить Windows 8 запускать 2 приложения Metro на каждом дисплее расширенного дисплея?

    Загрузка веб-страниц через список URL-адресов?

    Почему у нас есть reinterpret_cast на C ++, когда две цепные static_cast могут выполнять свою работу?

    Блокнот автоматически запускается при загрузке моего 64-разрядного настольного ПК с Windows 7

    Как конвертировать UTF-8 std :: string в UTF-16 std :: wstring?

    MongoDB, удалять объект из массива

    C # error: «Ссылка на объект требуется для нестатического поля, метода или свойства»

    GROUP_CONCAT ORDER BY

    Цитата Escape в строке подключения web.config

    Давайте будем гением компьютера.