我有一个ComboBox,当我重新填充它时,它似乎是一个相当耗时的任务。在进行了一些分析之后,我发现大部分时间都花在了ComboBox.Items.AddRange(数组)方法上。我已经在下面包含了一个示例方法,它显示了我如何执行ComboBox的重新填充。
public void Repopulate(IList<MyType> sortedList)
{
MyComboBox.BeginUpdate();
try
{
MyComboBox.Items.Clear();
MyComboBox.Items.AddRange(sortedList.ToArray());
}
finally
{
MyComboBox.EndUpdate();
}
}sortedList包含大约280个项目,并且有多达53个组合框需要重新填充。因此,重新填充所有这些控件可能需要相当长的时间(大约在高规格机器上运行700ms,在低规格机器上运行8000ms ),这对于我的要求来说太慢了。我试着将sortedList添加到一个新的IList中,花了大约1ms (在我的高规格机器上)。
我需要重新填充ComboBox,以便它花费的时间大大减少,理想情况下与IList的时间相似,但任何性能提高都会很好。到目前为止,我还找不到任何方法来提高重新人口的速度。
有没有人知道如何减少重新填充ComboBox所需的时间?
发布于 2012-05-16 21:20:11
您的问题可能是您已经启用了组合框的Sorted属性。当启用此功能并调用AddRange时,组合框将对所有这些项进行排序,如果您的项已经排序,则不需要这样做。
为了证明我的观点,我创建了两个组合框,它们使用10,000个排序的int和AddRange填充。唯一的区别是一个组合框启用了Sorted属性,而另一个没有。
notSortedCombo: 5ms
sortedCombo: 1140ms这会是你的问题吗?您可能有53个启用了排序属性的组合框吗?
发布于 2012-05-16 21:38:15
AddRange已经在幕后调用了BeginUpdate和EndUpdate,因此您自己调用它不会获得任何好处。
这为我节省了几毫秒的时间:
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项)填充组合框,然后在控件获得焦点时或在后台计时器中填充列表。
但请考虑减少屏幕上的控件数量。空白被认为是一件好事。
发布于 2012-05-16 23:39:28
关于UI虚拟化: WPF (Example)和WinForms都存在虚拟化。但只有一些控件支持它,如ListView、DataGridView、TreeView等。这些控件是为更大的数据量而设计的。如果可能,您可以切换到这些控件之一。
是否所有控件都同时显示在屏幕上?也许只有更新可见的才会有帮助。
另一种方法是异步更新组合框。如果您足够幸运,能够在.NET中使用新的异步/等待功能,这很容易做到。如果您想手动完成此操作,您可以只更新单个组合框,并将下一个组合框的更新安排在未来几毫秒之后(使用计时器或TPL)。这样,在更新发生时,UI至少仍能响应。
另一种方式是仅当用户聚焦于某个ComboBox时才更新列表。通常不需要更新内容,因为用户只有在使用ComboBox时才会看到它。
您还可以尝试在更新组合框的数据之前将其隐藏。或者,您可以告诉windows在修改内容时不要重新绘制UI (StackOverflow topic here)。但我还没有测试这是否真的提高了性能。
https://stackoverflow.com/questions/10617551
复制相似问题