我正在使用Windows ListView
控件来显示一个项目列表,总共最多可显示1000个项目,尽管一次列表视图中只有大约20个项目可见(listview使用的是详细信息视图)。
我经常将新项添加到列表视图的底部,并自动滚动到新添加的项(使用item.EnsureVisible()
),这样用户就可以看到最新的数据。当列表大小超过1000项时,我从列表中删除最古老的列表项(即索引0,列表视图顶部的项),以使其保持在1000项。
现在我的问题是:
每当列表视图中的选择发生更改时,与该项相关的其他详细信息将显示在表单的其他位置。当发生此选择更改时,我将停止自动滚动到新的项,以便用户的选定项保持在原来的位置(也就是说,当选择其中的项时,列表不会滚动到最新的项),并且只有在用户取消表单的其他详细信息部分时,才能重新启用自动滚动到最新项。
这一切都很好,除非我从列表视图中删除了最老的项(以确保列表不会超过1000项):当我删除最老的项时,列表视图会自动将所有内容滚动1(也就是说,我没有通过编程完成此滚动操作)。我意识到,如果选定的项目是最早的20个事件之一(这使得最早的20个事件成为可见的事件),它将别无选择,只能在删除最早的事件时滚动可见项,但是如果选择是在列表的中间,则不应该需要滚动列表查看项。
在删除最老的项时,是否可以防止列表视图由一个自动滚动?或者我必须通过确保可见的项目保持在我删除最古老的项目之前的位置,在移除它之后(这似乎是一个真正的麻烦)来绕过它吗?
发布于 2014-03-26 16:07:05
好的,这不是我理想的解决方案(但至少主要是有效的),在C#中(从VB.NET转换而来的StackOverflow语法高亮显示器可以正确地显示它,所以对任何类型的输入都表示歉意!)
任何更好的解决方案,请建议他们!
// loop through every item in the list from the top, until we find one that is
// within the listview's visible area
private int GetListViewTopVisibleItem()
{
foreach (ListViewItem item In ListView1.Items)
{
if (ListView1.ClientRectangle.IntersectsWith(item.GetBounds(ItemBoundsPortion.Entire)))
{
// +2 as the above intersection doesn't take into account the height
// of the listview's header (in Detail mode, which my listview is)
return (item.Index + 2);
}
}
// failsafe: return a valid index (which won't be used)
return 0;
}
private void RemoveOldestItem()
{
// pause redrawing of the listview while we fiddle...
ListView1.SuspendLayout();
// if we are not auto-scrolling to the most recent item, and there are
// still items in the list:
int TopItemIndex = 0;
if (!AllowAutoScroll && (ListView1.SelectedItems.Count > 0))
TopItemIndex = GetListViewTopVisibleItem();
// remove the first item in the list
ListView1.Items.RemoveAt(0);
// if we are not auto-scrolling, and the previous top visible item was not
// the one we just removed, make that previously top-visible item visible
// again. (We decrement TopItemIndex as we just removed the first item from
// the list, which means all indexes have shifted down by 1)
if (!AllowAutoScroll && (--TopItemIndex > 0))
ListView1.Items(TopItemIndex).EnsureVisible();
// allow redraw of the listview now
ListView1.ResumeLayout()
}
(当然,这假定所选的项当前可见,否则它就没有太多意义;不过,在我的场景中,它总是可见的,除非所选的事件是从列表顶部删除的事件(在这种情况下,不再选择任何事件,因此问题就消失了)
https://stackoverflow.com/questions/22659439
复制相似问题