Get First Visible Item in WPF ListView C#
This was so painful to get working:
HitTestResult hitTest = VisualTreeHelper.HitTest(SoundListView, new Point(5, 5));
System.Windows.Controls.ListViewItem item = GetListViewItemFromEvent(null, hitTest.VisualHit) as System.Windows.Controls.ListViewItem;
And the function to get the list item:
System.Windows.Controls.ListViewItem GetListViewItemFromEvent(object sender, object originalSource)
{
DependencyObject depObj = originalSource as DependencyObject;
if (depObj != null)
{
// go up the visual hierarchy until we find the list view item the click came from
// the click might have been on the grid or column headers so we need to cater for this
DependencyObject current = depObj;
while (current != null && current != SoundListView)
{
System.Windows.Controls.ListViewItem ListViewItem = current as System.Windows.Controls.ListViewItem;
if (ListViewItem != null)
{
return ListViewItem;
}
current = VisualTreeHelper.GetParent(current);
}
}
return null;
}
After trying to figure out something similar, I thought I would share my result here (as it seems easier than the other responses):
Simple visibility test I got from here.
private static bool IsUserVisible(FrameworkElement element, FrameworkElement container)
{
if (!element.IsVisible)
return false;
Rect bounds =
element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
var rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}
Afterwards you can loop through the listboxitems and use that test to determine which are visible. Since the listboxitems are always ordered the same the first visible one in this list would be the first visible one to the user.
private List<object> GetVisibleItemsFromListbox(ListBox listBox, FrameworkElement parentToTestVisibility)
{
var items = new List<object>();
foreach (var item in PhotosListBox.Items)
{
if (IsUserVisible((ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(item), parentToTestVisibility))
{
items.Add(item);
}
else if (items.Any())
{
break;
}
}
return items;
}
I can't believe there isn't an easier way...
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/2d527831-43aa-4fd5-8b7b-08cb5c4ed1db