Запись элементов, видимых пользователю в ListBox - PullRequest
4 голосов
/ 27 мая 2011

У меня есть ListBox или DataGrid, заполненный тысячами записей. Я хотел бы знать элементы, которые просматривал пользователь (прокрутка, поиск или другое). Как я могу сказать, что видно пользователю в ListBox?

Бонус: установите таймер так, чтобы элемент отображался в течение как минимум N миллисекунд (если пользователь просто нажимает полосу прокрутки).

Обновление: Это почти дубликат Получить элементы в списке - но решения, которое он дает, используя "SelectedItems", недостаточно. Мне нужно знать, выбраны они или нет!

1 Ответ

2 голосов
/ 30 мая 2011

Все, что вам нужно сделать, это получить базовую StackPanel, которая находится внутри ListBox.У него достаточно информации о том, какие элементы отображаются.(Он реализует интерфейс IScrollInfo).

Чтобы получить базовый StackPanel (или фактически VirtualizingStackPanel) из заданного ListBox, нам нужно будет использовать VisualTreeHelper для прохождения через Visual Tree и искать VirtualizingStackPanel, например, так:

    private VirtualizingStackPanel GetInnerStackPanel(FrameworkElement element)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
        {
            var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;

            if (child == null) continue;

            Debug.WriteLine(child.ToString());

            if (child is VirtualizingStackPanel) return child as VirtualizingStackPanel;

            var panel = GetInnerStackPanel(child);

            if (panel != null)
                return panel;
        }

        return null;

    }

Теперь, когда у нас есть StackPanel, мы очень близки.StackPanel имеет свойства VerticalOffset и ViewportHeight (оба из IScrollInfo), которые могут дать нам всю необходимую нам информацию.

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        var theStackPanel = GetInnerStackPanel(MyListBox);

        List<FrameworkElement> visibleElements = new List<FrameworkElement>();

        for (int i = 0; i < theStackPanel.Children.Count; i++)
        {

            if (i >= theStackPanel.VerticalOffset && i <= theStackPanel.VerticalOffset + theStackPanel.ViewportHeight)
            {
                visibleElements.Add(theStackPanel.Children[i] as FrameworkElement);
            }
        }


        MessageBox.Show(visibleElements.Count.ToString());
        MessageBox.Show(theStackPanel.VerticalOffset.ToString());
        MessageBox.Show((theStackPanel.VerticalOffset + theStackPanel.ViewportHeight).ToString());

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