删除最旧的项目时阻止ListView垂直滚动

时间:2014-03-26 11:22:39

标签: c# .net vb.net winforms

我正在使用Windows窗体ListView控件来显示项目列表,总共最多1000个项目,但一次只有大约20个项目在列表视图中可见(列表视图使用详细信息视图)。

我经常在列表视图的底部添加新项目,并自动滚动到新添加的项目(使用item.EnsureVisible()),以便用户可以看到最新的数据。当列表大小超过1000个项目时,我从列表中删除最旧的列表项(即索引0,列表视图顶部的列表项),以使其保持在1000个项目。

现在我的问题:

每当列表视图中的选择发生变化时,与该项目相关的其他详细信息将显示在表单的其他位置。当发生此选择更改时,我停止自动滚动到新项目,以便用户选择的项目保持原样(即,当选择其中的项目时,列表不会滚动到最新项目),并且仅 - 当用户驳回表单的其他详细信息时,启用自动滚动到最新版本。

这一切正常,除了,当我从列表视图中删除最旧的项目时(为了确保列表不超过1000项):当我删除最旧的项目时,列表视图滚动所有内容自动加1(即我以编程方式完成此滚动操作)。我意识到如果所选项目是最早的20个事件之一(这使得最早的20个事件成为可见的事件),它将别无选择,只能在最早删除时滚动可见项目,但如果选择的话,则说,在列表的中间,它不应该滚动列表视图项。

当我删除最旧的项目时,有什么方法可以阻止列表视图自动向上滚动吗?或者我是否必须通过确保可见物品保留在我移除最旧物品之前的位置,然后将其移除(这看起来真的很麻烦)?

1 个答案:

答案 0 :(得分:0)

好吧,这是我不太理想(但至少大部分都在工作)的解决方案,在C#中(从VB.NET转换,因此StackOverflow的语法高亮显示器可以正确显示它,所以对于任何拼写错误道歉!)。< / p>

任何更好的解决方案,请建议他们!

// 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()
}

(当然,这假定所选项目当前可见,否则它没有多大意义;它总是 在我的场景中可见,除非选中的事件是从列表顶部删除的事件(在这种情况下,不再选择任何内容,因此问题就会消失)。)