防止添加新项目时ListView自动水平滚动

本文关键字:水平 滚动 ListView 添加 新项目 | 更新日期: 2023-09-27 18:28:44

我在细节视图中使用了一个ListView控件,VirtualMode设置为true,我发现每当添加新项目时,水平滚动条都会设置在最左边的位置。如果ListView未处于虚拟模式,则不会发生这种情况更新:如果不启用视觉样式,也不会发生这种情况

您可以通过在详细信息模式中创建一个包含2列的简单ListView并添加以下内容来看到这一点:

Timer timer = new Timer();
public Form1()
{
    this.InitializeComponent();
    this.listView1.VirtualMode = true;
    this.listView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView1_RetrieveVirtualItem);
    this.listView1.VirtualListSize = 10;
    timer.Interval = 250;
    timer.Tick += new EventHandler(t_Tick);
    timer.Start();
}
void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    e.Item = new ListViewItem(new string[] {"Test", ""});
}
void t_Tick(object sender, EventArgs e)
{
    this.listView1.VirtualListSize += 1;
}

向右滚动列表视图以查看此效果。

我该如何阻止这种情况的发生?我有一个应用程序,其中的项目不断添加到列表视图中,因此这种行为非常分散注意力。

防止添加新项目时ListView自动水平滚动

这似乎是一个已知的错误:ListView在虚拟模式下错误地滚动

微软对Connect报告的最后一条评论是:

这是底层Win32控件的问题。我们将无法解决这个问题,操作系统团队将需要解决这个问题。

当然,那是在2005年,所以也许它在Win 8中被修复了?


与此同时,解决方法似乎是:

创建继承ListView的新类,并编写以下代码:

private static FieldInfo _internalVirtualListSizeField;
static FlickerFreeListView()
{
    _internalVirtualListSizeField = typeof(ListView).GetField("virtualListSize", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance);
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
private IntPtr SendMessage(int msg, int wparam, int lparam)
{
    return SendMessage(new HandleRef(this, this.Handle), msg, wparam, lparam);
}
public void SetVirtualListSize(int size)
{
    if (size < 0)
    {
        throw new ArgumentException("ListViewVirtualListSizeInvalidArgument");
    }
    _internalVirtualListSizeField.SetValue(this, size);
    if ((base.IsHandleCreated && this.VirtualMode) && !base.DesignMode)
    {
        SendMessage(0x102f, size, 2);
    }
}

现在更新您的代码以使用SetVirtualListSize方法,而不是原始的VirtualListSize属性。

0x102f = LVM_SETITEMCOUNT
2 = LVSICF_NOSCROLL

参考:http://msdn.microsoft.com/en-us/library/bb761188%28VS.85%29.aspx