ScrollViewer's Viewport Height VS Actual Height [duplicate]

♀尐吖头ヾ 提交于 2019-11-27 16:25:06

问题


Both are quite general terms but I'm curious to know when these height will be different apart from the case we're using Virtualization?

One more question: I read on MSDN:

If CanContentScroll is true, the values of the ExtentHeight, ScrollableHeight, ViewportHeight, and VerticalOffset properties are number of items. If CanContentScroll is false, the values of these properties are Device Independent Pixels.

However I'm facing an issue with ViewPort Height: I've 2 listbox in application:
1. Which have Virtualization Enabled and CanContentScroll = True.
2. Which have no virtualization and CanContentScroll = True.

In ListBox 1 while drag-drop Viewport Height comes to 4/5 (Number of elements currently visible). However in ListBox 2 i get Viewport Height equal to Actual Height of Listbox.

Why this difference?

Few more findings:
1. Scrollable Height is number of items not visible in scrollviewer
2. Viewport Height is number of items visible in scrollviewer.
Thus Viewport Height + ScrollableHeight = Extent Height

Can someone please explain what's the difference between two listboxes? I need ViewPort hieght in case of Listbox 1


回答1:


the ActualHeight is the actual height of the ScrollViewer. The Viewport is what is visible from the ScrollViewers Content. So to answer your question: ViewportHeight differs from ActualHeight if the horizontal Scrollbar is visible by the Height of the Scrollbar.

so, to sum this up:

ActualHeight = ViewportHeight + HorizontalScrollbarHeight



回答2:


Finally This was the root cause:

You are encountering the differences between physical scrolling and logical scrolling.

As you have discovered, each has its tradeoffs.

Physical scrolling

Physical scrolling (CanContentScroll=false) just goes by pixels, so:

The viewport always represents exactly the same portion of your scroll extent, giving you a smooth scrolling experience, and but

The entire contents of the DataGrid must have all templates fully applied and be measured and arranged to determine the size of the scrollbar, leading to long delays during loading and high RAM usage, and It doesn't really scroll items so it doesn't understand ScrollIntoView very well Logical scrolling

Logical scrolling (CanContentScroll=true) calculates its scroll viewport and extent by items instead of pixels, so:

The viewport may show a different number of items at different times, meaning the number of items in the viewport as compared to the number of items in the extent varies, causing the scrollbar length to change, and

Scrolling moves from one item to the next and never in between, leading to "jerky" scrolling

but

As long as you're using VirtualizingStackPanel under the hood, it only needs to apply templates and measure and arrange the items that are actually visible at the moment, and

ScrollIntoView is much simpler since it just needs to get the right item index into view

Choosing between them

These are the only two kinds of scrolling provided by WPF. You must choose between them based on the above tradeoffs. Generally logical scrolling is best for medium to large datasets, and physical scrolling is best for small ones.

A trick to speed loading during physical scrolling is to make the physical scrolling better is to wrap your items in a custom Decorator that has a fixed size and sets its child's Visibility to Hidden when it is not visible. This prevents the ApplyTemplate, Measure and Arrange from occuring on the descendant controls of that item until you're ready for it to happen.

A trick to make physical scrolling's ScrollIntoView more reliable is to call it twice: Once immediately and once in a dispatcher callback of DispatcherPriority.ApplicationIdle.

Making logical scroll scrollbar more stable

If all your items are the same height, the number of items visible in the viewport at any time will stay the same, causing the scroll thumb size to stay the same (because the ratio with total number if items doesn't change).

It is also possible to modify the behavior of the ScrollBar itself so the thumb is always calculated to be a fixed size. To do this without any hacky code-behind:

  • Subclass Track to replace the calculation of Thumb position and size in MeasureOverride with your own
  • Change the ScrollBar template used
    for the logical-scrolling ScrollBar
    to use your subclassed Track instead of the regular one

  • Change the ScrollViewer template to explicitly set your custom ScrollBar template on the logical-scrolling ScrollBar
    (instead of using the default
    template)

  • Change the ListBox template to use explicitly set your custom
    ScrollViewer template on the
    ScrollViewer it creates

This means copying a lot of template code fom the built-in WPF templates, so it is not a very elegant solution. But the alternative to this is to use hacky code-behind to wait until all the templates are expanded, then find the ScrollBar and just replace the ScrollBar template with the one that uses your custom Track. This code saves two large templates (ListBox, ScrollViewer) at the cost of some very tricky code.

Using a different Panel would be a much larger amount of work: VirtualizingStackPanel is the only Panel that virtualizes, and only it and StackPanel to logical scrolling. Since you are taking advantage of VirtualizingStackPanel's virtualization abilities you would have to re-implement all of these plus all IScrollInfo info function plus your regular Panel functions. I could do something like that but I would allocate several, perhaps many, days to get it right. I recommend you not try it.

Courtesy - Physical Scrolling vs Logical Scrolling




回答3:


They can differ from the point of (specified) Height being evaluated to any given time during the (ongoing) rendering process.

From MSDN:

There is a difference between the properties of Height and Width and ActualHeight and ActualWidth. For example, the ActualHeight property is a calculated value based on other height inputs and the layout system. The value is set by the layout system itself, based on an actual rendering pass, and may therefore lag slightly behind the set value of properties, such as Height, that are the basis of the input change.

Because ActualHeight is a calculated value, you should be aware that there could be multiple or incremental reported changes to it as a result of various operations by the layout system. The layout system may be calculating required measure space for child elements, constraints by the parent element, and so on.



来源:https://stackoverflow.com/questions/5733738/scrollviewers-viewport-height-vs-actual-height

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!