Высота видового экрана ScrollViewer против фактической высоты [дубликат]

этот вопрос уже есть ответ здесь:

оба являются довольно общими терминами, но мне любопытно знать, когда эта высота будет отличаться от случая, когда мы используем виртуализацию?

еще один вопрос: Я читаю дальше. В MSDN:

если CanContentScroll имеет значение true, значения свойств ExtentHeight, ScrollableHeight, ViewportHeight и VerticalOffset-это количество элементов. Если CanContentScroll имеет значение false, значения этих свойств являются независимыми от устройства пикселями.

однако я столкнулся с проблемой с высотой окна просмотра: у меня есть 2 listbox в приложении:
1. У которых включена виртуализация и CanContentScroll = True.
2. Которые не имеют виртуализации и CanContentScroll = True.

в ListBox 1 при перетаскивании высота окна просмотра доходит до 4/5 (количество элементов, видимых в данный момент). Однако в ListBox 2 я получаю высоту окна просмотра, равную фактической высоте Listbox.

Почему такая разница?

несколько выводов:
1. Прокручиваемая высота-это количество элементов, не видимых в scrollviewer
2. Высота видового экрана-количество элементов, видимых в scrollviewer.
Таким Образом Высота Viewport + ScrollableHeight = Высота Экстента

может кто-нибудь объяснить, в чем разница между двумя списками? Мне нужен видовой экран hieght в случае Listbox 1

3 ответов


на ActualHeight - фактическая высота ScrollViewer. Окно просмотра-это то, что видно из содержимого ScrollViewers. Итак, чтобы ответить на ваш вопрос:ViewportHeight отличается от ActualHeight если горизонтальная полоса прокрутки видна Height полосы прокрутки.

Итак, подведем итог:

ActualHeight = ViewportHeight + HorizontalScrollbarHeight

наконец, это было основной причиной:

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

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

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

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

видовое окно всегда представляет точно такую же часть вашего экстента прокрутки, что дает вам плавную прокрутку, и но!--1-->

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

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

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

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

но

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

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

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

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

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

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

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

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

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

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

  • изменение шаблона ScrollViewer чтобы явно задать пользовательский Шаблон прокрутки на логическая прокрутка Скроллбара
    (вместо использования по умолчанию
    шаблон)

  • изменить шаблон списка для использования явно установите свой пользовательский
    Шаблон ScrollViewer на
    ScrollViewer он создает

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

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

вежливость - физическая прокрутка против логической прокрутки


они могут отличаться от точки (указан) Height оценивается в любой момент времени во время (текущего) процесса рендеринга.

С MSDN:

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

Потому Что ActualHeight является вычисляемым значением, вы должны быть зная, что может быть несколько или добавочные сообщаемые изменения результат различных операций система макета. Система компоновки может вычислять необходимый космос измерения для дочерних элементов, ограничения родительский элемент, и так далее.