Это не легко сделать! Несколько месяцев назад я написал служебный метод для приложения Windows Phone 7, который перечисляет элементы, которые в настоящее время видны в ItemsControl:
/// <summary>
/// Enumerates all the items that are currently visible in an ItemsControl. This
/// implementation works for both virtualized and non-virtualized panels.
/// </summary>
public static IEnumerable<FrameworkElement> GetItemsInView(this ItemsControl itemsControl)
{
// find the panel that hosts our items - this is 'cached'
// using the ItemsControl.Tag property to minimize visual tree
// navigation
Panel itemsHostPanel = itemsControl.Tag as Panel;
if (itemsHostPanel == null)
{
itemsHostPanel = itemsControl.Descendants<Panel>()
.Cast<Panel>()
.Where(p => p.IsItemsHost)
.SingleOrDefault();
itemsControl.Tag = itemsHostPanel;
}
VirtualizingStackPanel vsp = itemsHostPanel as VirtualizingStackPanel;
if (vsp != null)
{
// implementation for virtualizing lists
return GetItemsInView(itemsControl, vsp);
}
else
{
// implementation for non-virtualizing lists
return Enumerable.Range(0, itemsControl.Items.Count)
.Select(index => itemsControl.ItemContainerGenerator.ContainerFromIndex(index))
.Cast<FrameworkElement>()
.Where(container => container.GetRelativePosition(itemsControl).Y + container.ActualHeight > 0)
.Where(container => container.GetRelativePosition(itemsControl).Y < itemsControl.ActualHeight);
}
}
/// <summary>
/// Gets the items in view for a virtualizing list
/// </summary>
private static IEnumerable<FrameworkElement> GetItemsInView(this ItemsControl itemsControl, VirtualizingStackPanel vsp)
{
// iterate over each of the items in view
int firstVisibleItem = (int)vsp.VerticalOffset;
int visibleItemCount = (int)vsp.ViewportHeight;
for (int index = firstVisibleItem; index <= firstVisibleItem + visibleItemCount + 2; index++)
{
var item = itemsControl.ItemContainerGenerator.ContainerFromIndex(index) as FrameworkElement;
if (item == null)
continue;
yield return item;
}
}
Этот должен работать для WPF DataGrid. Как вы можете видеть, реализация зависит от того, виртуализировано ли представление.
Обратите внимание, этот код является частью проекта WP7Contrib, и можно увидеть здесь . У него есть зависимости от нескольких других утилит / методов расширения.