【问题标题】:Scrolling Issue with a large number of items in a WinForms ListboxWinForms列表框中大量项目的滚动问题
【发布时间】:2014-09-17 17:48:17
【问题描述】:

我注意到列表框 winforms 控件中有大量项目的问题。

在这个简单的测试用例示例中,我将 120,000 个字符串添加到列表框中。我最初使用绑定到 listbox.DataSource 的数据表遇到了这种情况,但它也可以通过这种方式重现:

listBox.BeginUpdate();
for(int x = 0; x < 120000; x++)
{
    listBox.Items.Add(x);
}
listBox.EndUpdate();

当我单击并从上到下拖动滚动按钮时,释放鼠标后,它会将滚动按钮移动到滚动条的中间。

这是一个屏幕截图,显示了当我将按钮从底部/底部附近放开时的位置(我是精确的,并且鼠标没有超出滚动条的边界)。

如果我现在单击滚动条按钮并将其向下移动到控件长度的 3/4/ 处,它现在会弹回到控件长度向下的大约 1/4 处。

有其他人看到过这个吗?是否有已知的解决方法? (我承认我还没有研究下一点)这个控件是否有像 datagridview 这样的“虚拟模式”动态加载选项,可能会偶然摆脱这个奇怪的小问题?

【问题讨论】:

  • 用于拖放的代码
  • 还将这个 `listBox.Items.Add(x);` 更改为 `listBox.Items.Add(x.ToString());` 看看它是否能提高效率.. 除了您正在实施以及正确使用 for 循环
  • 解决您的多个 cmets:我没有在列表框中使用任何拖放操作。很高兴看到有可用的虚拟模式。您是否偶然知道设置虚拟模式是否可以解决滚动问题?上面的代码 sn-p 是我刚刚敲出来的一个例子。如果我添加整数或字符串,这对滚动问题没有影响。 (我最初的问题发生在一个使用字符串而不是数字的应用程序中)
  • 我将您的 Drag 误读为拖放。当您更改代码以添加 x.ToString() 时会发生什么情况,您是否还研究过列表框的大小限制它可以包含的项目数..?

标签: c# winforms listbox scroll


【解决方案1】:

例如,如果您想在第一次加载表单时执行此操作,请设置属性及其虚拟大小 使用 ListView 而不是 ListBox

private void Form1_Load(object sender, EventArgs e)
{
    listView1.VirtualMode = true;
    listView1.VirtualListSize = 12000;
 }

【讨论】:

    【解决方案2】:

    恕我直言,您正在解决错误的问题。在您的列表框中拥有如此大量的项目的用例是什么。列表框的一般用途是供用户从列出的总体中进行选择。您的应用程序是否真的希望用户从如此庞大的选择列表中选择特定项目?

    您可以通过提供一种更好的方式来缩小选择范围,从而帮助您的用户(和您的表现)。

    【讨论】:

    • 答案或多或少是“是”。使用字符串 UI 函数可以跳转到记录和过滤列表,但是现在的实现,列表框确实“需要”滚动所有记录的能力。我可以重新实现它以仅显示特定类别的记录,而不是所有类别(但这会令人困惑,因为过滤器函数必须忽略这一点),但它仍然可能有大量记录(但也许最多 30,000 个/类别)。一个需要考虑的解决方案,但我宁愿(以及我刚刚调查的用户)宁愿它按原样工作。
    • 这将我推向了潜在的解决方法。我可以使用带有两个选项卡的小型选项卡式控件。每个都有一个列表框。一种用于搜索并仅在用户搜索搜索字符串时显示,另一种将强制用户选择一个类别,因此控件将显示更少的记录。如果他们以返回所有/大多数记录的方式进行搜索,问题仍然存在,但这将在大多数情况下避免问题。稍后我可能会编写自己的控件来完全解决这个问题
    • 在不知道您的应用在做什么以及用户如何实际使用列表框的情况下,很难说出正确的答案是什么。不过我会说,在我 20 多年构建最终用户应用程序的过程中,我从来没有找到一个可以接受的用例,可以将列表中的 10 万多个项目呈现给用户,而且我的用户社区中没有人会接受必须这样做处理这么长的列表。如果用户需要选择的值是列表中的 100K 项,用户该怎么办?
    • 您可能想在ux.stackexchange.com 上发布一些内容,以获得有关如何从用户角度管理这种大小的列表的一些反馈。
    • 谢谢。我认为最终你是对的。如果没有有效的搜索字符串,列表框的内容就不能有效地使用,但有时匹配的记录数是关键。我需要将这些功能分开来克服滚动错误,以防用户想要滚动如此大量的记录(我承认 - 如果你真的在寻找特定的东西而不是随机抽样,那将是疯狂的,其中事实通常是用户在浏览返回的记录时所做的事情)
    【解决方案3】:

    我注意到垂直滚动条中的列表框只能返回从滚动位置到最大 65535 的索引。如果添加的项目超过此值,则会出现滚动问题。但是,垂直滚动条控件没有这个问题。它最多可以滚动到 Int32.Max。我只是使用垂直滚动条控件而不是 ListBox 滚动条中的默认构建

    我添加了另一个垂直滚动条(vScrollBar1)并将它放在列表框的右侧以覆盖其原始列表框垂直滚动条。

    然后为我创建的垂直滚动条添加以下代码

    private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { listbox.TopIndex = 
    e.NewValue; }
    
    private void vScrollBar1_MouseEnter(object sender, EventArgs e)
        {
            vScrollBar1.Maximum = listbox.Items.Count;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多