How do I get the start index and number of visible items in a ListView?

前端 未结 7 1948
迷失自我
迷失自我 2020-12-21 02:37

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

相关标签:
7条回答
  • 2020-12-21 03:12

    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)
    
    0 讨论(0)
  • 2020-12-21 03:25

    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;
    }
    
    0 讨论(0)
  • 2020-12-21 03:26

    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
    
    0 讨论(0)
  • 2020-12-21 03:27
    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;
    
    }
    
    0 讨论(0)
  • 2020-12-21 03:29

    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)
    
    0 讨论(0)
  • 2020-12-21 03:33

    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.

    0 讨论(0)
提交回复
热议问题