问题
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.
- Get the item container, in this case a
GridViewItem
, using theGridView
'sItemContainerGenerator
. - Get the
GridView
'sScrollViewer
. You can search forFindVisualChild<T>
methods, there are plenty around. - 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 itsExtent
) of theScrollViewer
(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 Height
s. Horizontal, use the Width
s. Both, use both. I am going to do my example using the Horizontal/Width.
- Take the
HorizontalOffset
. This is your current 'lower bound' for the current viewable region. - Take the
HorizontalOffset
plus theViewportWidth
. This is the upper bound of the current viewable region. - 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