How to get ScrollViewer VerticalOffset into independent dev pixels for ItemsControl with CanContentScroll true

I have a list with CanContentScroll true and others false.

And I'm writing a behavior that I need to extract a scrollviewer from it and calculate the vertical scroll offset in device independent pixels.

Since CanContentScroll can be either true or false, I sometimes get logical units of units, while other physical pixels.

Therefore, I need to calculate pixel values โ€‹โ€‹in case CanContentScroll is true.

As an example: when scrolling through the list of three elements, VerticalOffset will give 3. How to convert this value of 3 to the vertical pixels used by the elements (which may vary in size)?

thanks

+6
source share
3 answers

You cannot calculate pixel values โ€‹โ€‹without effectively setting CanContentScroll = "False".

To find out the size in pixels, you will need to create containers of all elements and summarize the heights of all containers. To do this, you must first create all the containers. This would mean that you actually lost virtualization and effectively set CanContentScroll = "False". In this case, why use CanContentScroll = "True" in the first place?

What Nikolaiโ€™s code is trying to do is take responsibility for what CanContentScroll = "False" does, not giving you the smooth scroll that you might otherwise get.

More importantly, what problem does physical bias solve that you cannot solve with logical bias if you always know that CanContentScroll = "true"?

+4
source

You can simply summarize the sizes of the scroll elements as follows:

private void Button_Click(object sender, RoutedEventArgs e) { var scroller = GetScrollViewer(); var listBox = GetListBox(); double trueOffset; if (scroller.CanContentScroll) for (int i = 0; i < (int)scroller.VerticalOffset; i++) { var listBoxItem = (FrameworkElement)listBox.ItemContainerGenerator.ContainerFromIndex(i); trueOffset += listBoxItem.ActualHeight; } else trueOffset = scroller.VerticalOffset; this.Title = trueOffset.ToString(); } 

This simple code works well for listbox with variable elements

+2
source

I would try a different approach.

Paste your list with Scrollviewer and disable the scroll behavior of the list itself.

You can than measure the scrollviewer VerticalOffset outside the list.

 <TextBlock Grid.Row="0" Text="{Binding ElementName=scrollviewer, Path=VerticalOffset}"/> <ScrollViewer x:Name="scrollviewer" VerticalScrollBarVisibility="Auto" Grid.Row="1"> <ListBox ScrollViewer.CanContentScroll="False"> <ListBox.Items> <ListBoxItem>A</ListBoxItem> <ListBoxItem>B</ListBoxItem> <ListBoxItem>C</ListBoxItem> 
-1
source

Source: https://habr.com/ru/post/910504/


All Articles