How can I determine which items in a GridView that are visible in the current scroll window?

你说的曾经没有我的故事 提交于 2019-12-21 05:41:28

问题


I have a GridView in my main app page and I want to do some background processing for the items that are currently in view for the user (high priority), and then of course do the other items too (low priority).

I can access the ScrollBar and the ScrollViewer, but none of them appear to tell me which of my items are in the current scroll window. I could try to hack this in, but it gets tricky because the number of row/columns change based on the size of the scroll region.

http://msdn.microsoft.com/en-us/library/windows/apps/br209745.aspx http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.scrollviewer.aspx

Any help much appreciated!

thanks


回答1:


There are two general ways you can do this. The first is to get the GridViewItem's AutomationPeer, which actually has a direct method to call. Class information here. I've had problems getting this to actually be usable though. Luckily, there's a second answer. It will require some math to be done, but it's doable.

  1. Get the item container, in this case a GridViewItem, using the GridView's ItemContainerGenerator.
  2. Get the GridView's ScrollViewer. You can search for FindVisualChild<T> methods, there are plenty around.
  3. Do MyGridViewItem.TransformToVisual(MyGridViewScrollViewer).TransformPoint(new Point(0, 0)); This will get you the top left corner of the item, relative to the entire scrollable panel (known as its Extent) of the ScrollViewer (this will be important later).

This will return to you a Point object.

Next, we'll need to find out the range of X values that are currently being displayed in the ScrollViewer.

Note: If you're using a Vertical scrolling ScrollViewer, use the Heights. Horizontal, use the Widths. Both, use both. I am going to do my example using the Horizontal/Width.

  1. Take the HorizontalOffset. This is your current 'lower bound' for the current viewable region.
  2. Take the HorizontalOffset plus the ViewportWidth. This is the upper bound of the current viewable region.
  3. If your Point.X is greater than your lower bound and less than your upper bound, then the item is visible.

If you further need to find out if the whole item is visible, do this same calculation for Point.X + GridViewItem.Width.

Hope this helps, and happy coding!




回答2:


You can use VisualTreeHelper to scan the visual tree as Nate suggests, but this is usually not recommended at runtime, especially for tight loops (e.g. checking lots of GridViewItem objects) or complex visual trees. You could do a minor improvement and only calculate the position of these items once and then do a simplified check based on the ScrollViewer.ViewChanged event and offset values, but that still seems a bit too complicated.

If your GridView uses an ItemsPanel that supports virtualization (e.g. the default WrapGrid) - most of the items that are actually loaded into GridView items are actually visible or not far off the screen, so if you bind your GridView to a collection of view models using ItemsSource - you can figure out when these items are accessed by binding to their properties or handling Loaded/Unloaded events on the ItemTemplate and call back to the view models to know when they are getting accessed. That way you can start loading these items when they first start showing up on screen and leave the logic to determine whether they should be loaded to the list control virtualization implementation in the platform.



来源:https://stackoverflow.com/questions/16705800/how-can-i-determine-which-items-in-a-gridview-that-are-visible-in-the-current-sc

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