使用WinForms显示包含大量组合框控件的选项卡速度较慢

使用WinForms显示包含大量组合框控件的选项卡速度较慢,winforms,optimization,combobox,performance,Winforms,Optimization,Combobox,Performance,我已经设置了一个带有多个选项卡的对话框。其中一个包含20个组合框,每个组合框包含100多个项目,添加方式如下: foreach (var x in collection) { string text = FormatItem (x); combo.Items.Add (text); } 所以这些东西一点也不新奇。它们是纯字符串,在创建对话框时,组合框会被填充。这几乎是瞬间发生的 然而,当用户第一次单击包含所有这些组合框的选项卡时,GUI会冻结几秒钟(而我正在一台真正健壮的机器上

我已经设置了一个带有多个选项卡的对话框。其中一个包含20个组合框,每个组合框包含100多个项目,添加方式如下:

foreach (var x in collection)
{
    string text = FormatItem (x);
    combo.Items.Add (text);
}
所以这些东西一点也不新奇。它们是纯字符串,在创建对话框时,组合框会被填充。这几乎是瞬间发生的

然而,当用户第一次单击包含所有这些组合框的选项卡时,GUI会冻结几秒钟(而我正在一台真正健壮的机器上运行)

我加载了
System.Windows.Forms
的符号,并试图在程序卡住时闯入调试器。我发现的是具有以下调用的堆栈跟踪:

System.Windows.Forms.Control.CreateHandle()
System.Windows.Forms.ComboBox.CreateHandle()
System.Windows.Forms.Control.CreateControl(...) x 3
System.Windows.Forms.Control.SetVisibleCore(true)
System.Windows.Forms.TabPage.Visible.set(true)
这会导致大量的本机转换,
WndProc
调用等。我想每个组合框中的每个项目都会发生这种情况。呸

显然,我无法优化WinForms。但也许我可以采取一些行动来避免在我可怜的GUI上迷失方向?有什么想法吗

Nota bene:

  • 我没有在组合框上附加事件处理程序,当控件真正创建时可以调用这些事件处理程序

  • 如果我在创建并填充表单之后尝试访问组合框的
    句柄
    属性,我会在那一刻支付罚金,而不是在选项卡第一次可见时支付罚金。但是在创建表单时必须等待几秒钟也是不可接受的。我真的很想摆脱漫长的准备时间

  • 应用
    BeginUpdate
    EndUpdate
    的想法在这里并不适用:它们应该用来防止控件在其项目列表被填充时重新绘制。但在我的例子中,问题发生在控件设置好之后


  • 你所说的与我所观察到的不一致…:

    但是您是否尝试过使用.BeginUpdate/.EndUpdate


    您可以尝试的另一件事是在需要之前不填充框。延迟它直到盒子获得焦点,例如。。。(如果捕获下拉事件,某些用户可能会对上/下箭头键不起作用感到恼火。)

    不是迭代集合,设置ComboBox.DataSource不是一个可行且更快的替代方案吗

    comboBox1.DataSource = myCollection1;
    comboBox2.DataSource = myCollection2;
    comboBox3.DataSource = myCollection3;
    // and so on...
    
    下面是一个更完整的示例:

    public class Entity
        {
            public string Title { get; set; }
            public override string ToString()
            {
                return Title;
            }
        }
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                List<Entity> list = new List<Entity>
                                        {
                                            new Entity {Title = "Item1"},
                                            new Entity {Title = "Item2"},
                                            new Entity {Title = "Item3"}
                                        };
    
                comboBox1.DataSource = list;
    
            }
    
    公共类实体
    {
    公共字符串标题{get;set;}
    公共重写字符串ToString()
    {
    返回标题;
    }
    }
    公共部分类Form1:Form
    {
    公共表格1()
    {
    初始化组件();
    列表=新列表
    {
    新实体{Title=“Item1”},
    新实体{Title=“Item2”},
    新实体{Title=“Item3”}
    };
    comboBox1.DataSource=列表;
    }
    
    一个表单上有很多控件可能是个问题。我曾经有一个表单动态创建了50-100个文本框控件。加载速度很慢


    我们通过使用datagrid解决了这个问题。它是一个针对大量数据进行优化的控件。我不知道您的确切要求是什么,但它可能会起作用。

    到目前为止,我尝试的所有操作都失败了,无法加快包含所有组合框的选项卡的第一次显示。数据绑定也没有帮助


    最后,我决定通过做一个技巧来解决这个问题,类似于所建议的,即当焦点第一次到达组合时,只填充
    集合。这仍然会产生明显的延迟,即创建所有项的时间(在
    开始更新
    结束更新
    方法调用对内),但这是可以忍受的(大约200毫秒,而在我最初的场景中是几秒钟)。

    我刚刚遇到了同样的问题,在组合框中填充大约4000k个项目的速度慢得令人无法接受

    我在表单的OnLoad事件处理程序中填充组合,但是,当我将此代码转换为构造函数时,在InitializeComponent()之后,根本没有延迟


    我猜在OnLoad中执行此操作会导致重新绘制组合,从而导致延迟?无论如何,我只是想添加此操作,以防在这种情况下对其他人有用。

    是的,延迟控件项的填充可能会起作用…但这需要相当多的调整,因为我无法使用
    selectedIdex
    和其他类似属性。我在.Net Framework 4.7中看到了相同的问题!它尚未修复!