简体   繁体   中英

Getting valid values from ScrollInfo of a ListBox

I have a ListBox, the issue I'm facing is trying to get valid values from the IScrollInfo object.

I know from setting MaxHeight on the ListBox to 150 that the ViewportHeight should be around this size and the full height is twice as big so the ExtentHeight should be about 300.

I get the following values from:
_scrollInfo.ExtentHeight = 13
_scrollInfo.ViewportHeight = 7
_scrollInfo.VerticalOffset = varying but 1-6

The values from:
UIElement scrollable = _scrollInfo as UIElement;
seem to be correct.
scrollable.RenderSize.Height = 146 which is roughly right.

What I'm wondering about is:

When my ListBox control is first loaded it is bound to an empty ObservableCollection . It is not until later that items are added. Could it be that the IScrollInfo object is retaining these initial values from when the ListBox was empty?

The other thing the IScrollInfo object is a VirtualizingStackPanel could this have any bearing on the matter?

[EDIT]
Have tried changing the VirtualizingStackPanel to StackPanel , however I am still getting the same results.

This behaviour is given by ScrollViewer.CanContentScroll="True" It basically says, that you are not allowed to scroll by pixels, but only by items.

Consider this example:

private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    var scrollViewer = (ScrollViewer) sender;
    Trace.WriteLine(string.Format("ExtentHeight: {0}, ViewportHeight : {1}, VerticalOffset : {2}",
        scrollViewer.ExtentHeight, scrollViewer.ViewportHeight, scrollViewer.VerticalOffset));
}


<ScrollViewer Height="150" ScrollChanged="ScrollViewer_ScrollChanged" CanContentScroll="True">
    <VirtualizingStackPanel>
        <Rectangle Height="40" Margin="5" Fill="Red" />
        <Rectangle Height="40" Margin="5" Fill="Green" />
        <Rectangle Height="40" Margin="5" Fill="Blue" />
        <Rectangle Height="40" Margin="5" Fill="Red" />
        <Rectangle Height="40" Margin="5" Fill="Green" />
        <Rectangle Height="40" Margin="5" Fill="Blue" />
        <Rectangle Height="40" Margin="5" Fill="Red" />
    </VirtualizingStackPanel>
</ScrollViewer>

you get following output:

ExtentHeight: 7, ViewportHeight : 3, VerticalOffset : 0   
ExtentHeight: 7, ViewportHeight : 3, VerticalOffset : 1
ExtentHeight: 7, ViewportHeight : 3, VerticalOffset : 2   

but when you set CanContentScroll="False" :

ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 3,01724137931035
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 6,03448275862069
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 9,05172413793104
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 12,0689655172414
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 15,0862068965517
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 18,1034482758621
ExtentHeight: 350, ViewportHeight : 150, VerticalOffset : 21,1206896551724

In the first example you are scrolling by items. You have seven items, so ExtentHeight is 7 and 3 items are visible, so ViewportHeight is 3.

In the second example you are scrolling by pixels, so ExtentHeight is total height of all items and viewport height is height of scrollviewver

Moral of the story is, that in some scenarios you dont want to measure size of all items, because it could have negative performance effect. It's the case especially when virtualizing elements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM