问题描述
我有一个ListBox或DataGrid填充数千条目。我想知道用户看过的项目(滚动,搜索或其他)。如何知道ListBox中的用户可以看到哪些内容?奖励:设置一个计时器,使该项目必须显示至少N毫秒(在事件,用户只是拉下滚动条)。
更新:这是一个几乎重复的 - 但是使用SelectedItems提供的解决方案是不够的。我需要知道这些项目是否被选中?
所有你需要做的是获取底层的StackPanel在ListBox里面它有足够的信息显示哪些元素。 (它实现了接口IScrollInfo)。
要从给定的ListBox获取底层的StackPanel(或者实际上是VirtualizingStackPanel),我们必须使用VisualTreeHelper通过Visual树,并寻找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为VirtualizingStackPanel)将child返回为VirtualizingStackPanel;
var panel = GetInnerStackPanel(child);
if(panel!= null)
返回面板;
}
返回null;
}
现在我们有StackPanel,我们非常接近。 StackPanel具有属性 VerticalOffset
和 ViewportHeight
(均来自 IScrollInfo
private void button1_Click(object sender,RoutedEventArgs e)
{
var theStackPanel = GetInnerStackPanel(MyListBox);
列表< 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());
}
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());
}
这篇关于记录用户在ListBox中可见的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!