I have a listview working in virtual mode, in the LargeIcons view. Retrieves are expensive, so I want to ask for the data for all the visible items. How do I get the start
THE REAL Answer is :
* get the ScrollViewer of the ListView.
* ScrollViewer.VerticalOffset is the index of first shown item.
* ScrollViewer.ViewportHeight is the number of items shown.
To get the ScrollViewer, you will need a function, FindDescendant(FrameworkElement, Type) that will search within the childs of the ListView. Call it after Window was loaded.
Code in VB.Net and in C# :
Public Function FindDescendant(ByVal MyElementToSeek As FrameworkElement, _
ByVal TypeToFind As Type) As FrameworkElement
If MyElementToSeek Is Nothing Then Return Nothing
If MyElementToSeek.GetType() = TypeToFind Then Return MyElementToSeek
For i = 0 To VisualTreeHelper.GetChildrenCount(MyElementToSeek) - 1
Dim OneChild = TryCast(VisualTreeHelper.GetChild(MyElementToSeek, i), FrameworkElement)
Dim Result = FindDescendant(OneChild, TypeToFind)
If Result IsNot Nothing Then Return Result
Next
Return Nothing
End Function
.
public FrameworkElement FindDescendant(FrameworkElement MyElementToSeek,
Type TypeToFind)
{
if (MyElementToSeek == null) return null;
if (MyElementToSeek.GetType() == TypeToFind) return MyElementToSeek;
for (i = 0;
(i<= (VisualTreeHelper.GetChildrenCount(MyElementToSeek) - 1)); i++)
{
object OneChild = TryCast(VisualTreeHelper.GetChild(MyElementToSeek, i),
FrameworkElement);
object Result = FindDescendant(OneChild, TypeToFind);
if (Result) return Result;
}
return null;
}
}
' MyScrollViewer = FindDescendant(MyListView, ScrollViewer)
Just off the top of my head, and I haven't tested this but could you do:
private void GetIndexes(ListView vv, out int startidx, out int count)
{
ListViewItem lvi1 = vv.GetItemAt(vv.ClientRectangle.X+6, vv.ClientRectangle.Y + 6);
ListViewItem lvi2 = vv.GetItemAt(vv.ClientRectangle.X+6, vv.ClientRectangle.Bottom-10);
startidx = vv.Items.IndexOf(lvi1);
int endidx = vv.Items.IndexOf(lvi2);
if (endidx == -1) endidx = vv.Items.Count;
count = endidx - startidx;
}
Try this:
If ListView.Items.Count > 0 Then
Dim lvi As ListViewItem = ListView.TopItem
If lvi Is Nothing Then Return
Dim startIndex As Integer = lvi.Index
Dim lastVisible As Integer = startIndex
While ListView.Items(lastVisible).Bounds.Bottom < Me.lvRes.Bounds.Bottom
lastVisible += 1
End While
lastVisible -= 1
End If
foreach (var t in listView1.Items)
{
var lvitem = listView1.ItemContainerGenerator.ContainerFromItem(t) as ListViewItem;
if (lvitem == null) continue;
//lvitem will = null if it is not visible
// otherwise do stuff with lvitem such as:
lvitem.Foreground = Brushes.Green;
}
I know this post is old ..... Wrong
MyScrollViewer = FindDescendant(MyListView, ScrollViewer)
Right is:
Dim Myscrollviwer As ScrollViewer
Myscrollviwer = FindDescendant(myListView3, GetType(ScrollViewer))
MsgBox(Myscrollviwer.VerticalOffset)
You could iterate through subsequent items, checking their visibility until you reach the one that isn't visible. This would give you a count of the visible items.
For example, something like:
for (int index = 0; index < list.Items.Count; index++)
{
if (list.ClientRectangle.IntersectsWith(item.GetBounds(ItemBoundsPortion.Entire)))
{
// Add to the list to get data.
}
else
{
// We got them all.
break;
}
}
I'm not sure what effect sorting would have on this though.