Как получить начальный индекс и количество видимых элементов в ListView? - PullRequest
4 голосов
/ 16 декабря 2008

У меня есть просмотр списка, работающий в виртуальном режиме, в представлении LargeIcons. Извлечения дорогие, поэтому я хочу запросить данные для всех видимых элементов. Как получить начальный индекс и общее количество видимых элементов?

Обновление: мне известно о событии CacheVirtualItems. Сторонней базе данных, которую мы используем, требуется ~ 3 секунды для извлечения одной записи, но ~ 4 секунды для извлечения тысячи записей, поэтому мне приходится делать их большими блоками. Мне нужно убедиться, что видимые записи находятся среди тех, которые мы извлекаем, поэтому мне нужно знать начальный индекс и общее количество видимых элементов. Если это невозможно, мне придется найти обходной путь (который, вероятно, будет включать использование DataGridView с загрузкой ячеек изображения для имитации представления LargeIcons), но я хотел бы сделать это правильно, если это возможно.

Ответы [ 7 ]

2 голосов
/ 25 июня 2012

НАСТОЯЩИЙ Ответ:
* получить ScrollViewer из ListView.
* ScrollViewer.VerticalOffset - это индекс первого показанного элемента.
* ScrollViewer.ViewportHeight - количество отображаемых элементов.

Чтобы получить ScrollViewer, вам понадобится функция, FindDescendant (FrameworkElement, Type), который будет искать в детях Посмотреть список. Вызовите его после того, как Window был загружен.

Код в VB.Net и в 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)
1 голос
/ 17 декабря 2008

С головы до головы, и я не проверял это, но не могли бы вы сделать:

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;
}
1 голос
/ 16 декабря 2008

Вы можете перебирать последующие элементы, проверяя их видимость, пока не дойдете до того, который не отображается. Это даст вам количество видимых предметов.

Например, что-то вроде:

        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;
            }
        }

Хотя я не уверен, какой эффект окажет на это сортировка.

0 голосов
/ 16 октября 2016

Я знаю, что этот пост старый ..... Неправильно

MyScrollViewer = FindDescendant(MyListView, ScrollViewer)

Право это:

Dim Myscrollviwer As ScrollViewer

Myscrollviwer = FindDescendant(myListView3, GetType(ScrollViewer))
MsgBox(Myscrollviwer.VerticalOffset)
0 голосов
/ 10 января 2012

Попробуйте это:

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 голосов
/ 30 мая 2011
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 голосов
/ 16 декабря 2008

Вы видели событие CacheVirtualItems? Элемент управления будет запрашивать диапазон элементов вместо одного за другим. То есть, если прокрутить, он все равно может попросить только по одному за раз. Но pagedown / up запустит механизм кэширования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...