Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the ScrollViewer's VerticalOffset in dev independent pixels for an ItemsControl with CanContentScroll true

Tags:

c#

.net

wpf

I have a listbox with CanContentScroll true, but others that are false.

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

Since the CanContentScroll can be either true or false I sometimes get logical item units while other times physical pixels.

So I need to calculate the pixel values in case CanContentScroll is true.

For an example: when the listbox is scrolled by three items VerticalOffset will give 3. How to convert this 3 to the vertical pixels used by the items (which can vary in size)?

Thanks

like image 925
Marino Šimić Avatar asked Mar 12 '12 13:03

Marino Šimić


2 Answers

You cannot calculate the values in pixels without effectively setting CanContentScroll="False".

To know the size in pixels you would need to create the containers of all the items and sum up the heights of all the containers. To do that you will need to generate all the containers first. Which would mean that you effectively lost virtualization and effectively set CanContentScroll="False". In that case why use CanContentScroll="True" in the first place?

What Nikolay's code tries to do is take on the burden of doing yourself what CanContentScroll="False" does without giving you the smooth scrolling that you would have otherwise gained.

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

like image 75
NVM Avatar answered Oct 14 '22 15:10

NVM


You can just sum sizes of scrolled items like this:

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 size items

like image 24
Nikolay Avatar answered Oct 14 '22 16:10

Nikolay