开发者

Record items visible to user in ListBox

I have a ListBox or DataGrid filled with thousands of entries. I would like to know items that the user has looked at (scrolling, searching or otherwise). How can I tell what is visible to the user in the ListBox?

Bonus: Set a timer so that the item has to be shown for a minimum of N milliseconds (in the event the user is just pulling down the scrollbar).

Update: This is a near duplicate of Get items in view within a listbox - but the solution it gives, using "SelectedItems", is not sufficient. I need to know 开发者_开发问答the items whether they are selected or not!


All you need to do is to get the underlying StackPanel that's inside the ListBox. It has enough information about which elements are showing. (It implements the interface IScrollInfo).

To get the underlying StackPanel (or actually VirtualizingStackPanel) from a given ListBox, we'll have to use VisualTreeHelper to go through the Visual Tree and look for the VirtualizingStackPanel, like so:

    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;

    }

Now that we have the StackPanel, we're very close. The StackPanel has the properties VerticalOffset and ViewportHeight (both coming from IScrollInfo) that can give us all the information we need.

    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());

    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜