组合框.项目.添加范围性能

本文关键字:范围 性能 添加 项目 组合 | 更新日期: 2023-09-27 18:34:15

我有一个ComboBox,当我重新填充它时,这似乎是一项非常耗时的任务。在做了一些分析之后,我发现大部分时间都花在ComboBox.Items.AddRange(Array(方法上。我在下面包含一个示例方法,它显示了我如何重新填充组合框。

public void Repopulate(IList<MyType> sortedList)
{
    MyComboBox.BeginUpdate();
    try
    {
        MyComboBox.Items.Clear();
        MyComboBox.Items.AddRange(sortedList.ToArray());
    }
    finally
    {
        MyComboBox.EndUpdate();
    }
}

sortedList 包含大约 280 个项目,并且有多达 53 个组合框需要重新填充。因此,重新填充所有这些控件可能需要相当长的时间(在高规格机器上约为 700 毫秒,在低规格机器上约为 8000 毫秒(,这对于我的要求来说太慢了。我尝试将排序列表添加到新的 IList 中,这花了大约 1 毫秒(在我的高规格机器上(。

我需要重新填充组合框,以便花费更少的时间,理想情况下与 IList 的时间相似,但任何性能提升都会很好。到目前为止,我还没有找到任何提高重新人口速度的方法。

有没有人知道我如何减少重新填充组合框所需的时间?

组合框.项目.添加范围性能

您的问题可能是您启用了组合框的 Sorted 属性。 启用此选项并调用 AddRange 组合框会对所有这些项目进行排序,如果您的项目已排序,则不需要这样做。

为了证明我的观点,我创建了两个组合框,它们使用 10,000 个排序的整数和 AddRange 填充。 唯一的区别是,一个组合框启用了 Sorted 属性,另一个组合框没有。 以下是生成的AddRange调用的时间(以毫秒为单位(

notSortedCombo: 5ms
sortedCombo: 1140ms

这可能是你的问题吗? 您能否有 53 个启用了排序属性的组合框?

AddRange已经在引擎盖下调用BeginUpdateEndUpdate,所以你自己调用它不会得到任何东西。

这为我节省了几毫秒:

public void Repopulate(IList<string> sortedList) {
  comboBox1.BeginUpdate();
  comboBox1.Items.Clear();
  foreach (string item in sortedList) {
    comboBox1.Items.Add(item);
  }
  comboBox1.EndUpdate();
}

更大的问题可能是设计:53 个组合框是向用户扔很多组合框 — 用户将无法同时与所有 53 个控件进行交互。 您可能会变得有点笨拙,只需使用可见值(1 项(填充组合框,然后在控件获得焦点或在后台计时器中填充列表。

但请考虑减少屏幕上的控件数量。 空白被认为是一件好事。

可以通过将组合框的属性FormattingEnabled更改为False来提高性能

问题在于,如果您不在设计器中"手动"指定项,而是以编程方式添加它们,Visual Studio 会将其保留为True

尝试,它为我解决了问题

关于 UI 虚拟化:WPF(示例(和 WinForms 都存在虚拟化。但只有一些控件支持它,如ListView,DataGridView,TreeView等。这些是为大量数据设计的控件。如果可能,您可以切换到这些控件之一。

所有控件是否同时在屏幕上可见?也许只有更新可见的会有所帮助。

另一种方法是异步更新组合框。如果你有幸在.NET中使用新的async/await东西,这很容易完成。如果要手动执行此操作,只需更新单个组合框,并计划将来几毫秒内更新下一个组合框(使用计时器或 TPL(。这样,在进行更新时,UI 至少仍具有响应性。

另一种方法是仅在用户聚焦某个 ComboBox 时才更新列表。通常不需要更新内容,因为用户只有在使用 ComboBox 时才能看到它。

您也可以尝试在更新其数据之前隐藏组合框。或者,您可以告诉窗口在修改内容时不要重绘 UI(此处为堆栈溢出主题(。但我还没有测试这是否真的提高了性能。