【问题标题】:Preventing a ListView from automatically horizontally scrolling when new items are added添加新项目时防止 ListView 自动水平滚动
【发布时间】:2012-04-08 03:41:52
【问题描述】:

我在详细信息视图中使用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;
}

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

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

【问题讨论】:

    标签: c# .net winforms listview scroll


    【解决方案1】:

    这似乎是一个已知错误:ListView in virtual mode scrolls incorrectly

    Microsoft 对该 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

    【讨论】:

    • 在错误报告中,水平滚动与垂直滚动之间似乎存在一些混淆,但列出的解决方法确实解决了我的问题(这表明问题不是在Win32 控件,但是哦!)
    • 我想我只是假设如果垂直滚动发生它也会影响水平滚动(显然它确实如此)。可能值得在错误报告中添加注释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多