简体   繁体   English

将控件添加到TableLayoutPanel的快速方法

[英]Fast way to add Controls to a TableLayoutPanel

I have to add a lot of Control objects to a TableLayoutPanel dynamically, what takes a significant amount of time. 我必须将大量Control对象动态地添加到TableLayoutPanel ,这要花费大量时间。 I also need to be able to access the controls via row- and column-index of the TableLayoutPanel and vice versa. 我还需要能够通过TableLayoutPanel行索引和列索引访问控件,反之亦然。

TableLayoutPanel.Controls has (as far as I know) 3 ways to add Control objects: TableLayoutPanel.Controls (据我所知)具有3种添加Control对象的方法:

  • .Add(Control) - inherited, position is -1,-1 with .GetCellPosition(Control) .Add(Control) -继承,位置为.GetCellPosition(Control) -1,-1
  • .Add(Control, column, row) - position and indexes are correct, but maybe a bit slow? .Add(Control, column, row) -位置和索引正确,但可能有点慢?
  • .AddRange (Control[]) - inherited, faster, shown position is correct (every cell is filled, if necessary columnspans are set afterwards), but position is -1,-1 with .GetCellPosition(Control) .AddRange (Control[]) -继承的,更快的,显示的位置是正确的(填充了每个单元格,如果需要,则随后设置了列跨度),但是使用.GetCellPosition(Control)位置为-1,-1

Is there a way to combine the advantages of .Add(Control, column, row and .AddRange(Control[]) , ie to add a lot of Control objects fast to a TableLayoutPanel while still being able to get the position of a Control programmatically? 有没有一种方法可以结合.Add(Control, column, row.AddRange(Control[])的优点,即快速将许多Control对象添加到TableLayoutPanel同时仍然能够以编程方式获取Control的位置?


EDIT to include some information from the comments: 编辑以包括评论中的一些信息:

  • There are up to 1000 controls added 最多添加1000个控件
  • I already use SuspendLayout() and ResumeLayout() 我已经使用SuspendLayout()ResumeLayout()
  • The TableLayoutPanel takes about 2 seconds to load. TableLayoutPanel大约需要2秒钟才能加载。 According to the profiler roughly 50% of the time is spent with adding Controls, 20% with ResumeLayout() 根据分析器,大约50%的时间用于添加控件,而20%的时间用于ResumeLayout()

EDIT: MCVE 编辑:MCVE
My original code is more complex, but this is an example of a TableLayoutPanel where adding the controls takes most of the time spent (2/3). 我的原始代码更加复杂,但这是TableLayoutPanel的示例,其中添加控件花费了大部分时间(2/3)。 I am searching for a way to speed this up. 我正在寻找加快速度的方法。

public class FormTLPTest : Form
{
    public FormTLPTest()
    {
        Height = 800;
        Width = 800;

        TableLayoutPanel tlp = new TableLayoutPanel();
        tlp.Dock = DockStyle.Fill;
        tlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
        tlp.AutoScroll = true;

        Controls.Add(tlp);

        tlp.ColumnCount = 7;
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0F));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 30));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20));

        tlp.SuspendLayout();

        for (int i = 0; i<700; i++)
        {
            Button btn1 = new Button();
            Label lb2 = new Label();
            Label lb3 = new Label();
            Label lb4 = new Label();
            TextBox tb5 = new TextBox();
            Button btn6 = new Button();
            Button btn7 = new Button();

            foreach (Control c in new Control[] { btn1, lb2, lb3, lb4, tb5, btn6, btn7})
            {
                c.Margin = new Padding();
                c.Dock = DockStyle.Fill;
                c.BackColor = Color.White;
            }

            btn1.FlatStyle = FlatStyle.Flat;
            btn6.FlatStyle = FlatStyle.Flat;
            btn7.FlatStyle = FlatStyle.Flat;

            btn1.Text = "1";
            lb2.Text = "Some longer Text - it contains information. Don't know what I should write to fill the space";
            lb3.Text = "Short Text";
            lb4.Text = "Short Text";
            tb5.Text = "5";
            btn6.Text = "Button";
            btn7.Text = "+";

            tlp.Controls.Add(btn1, 0, i);
            tlp.Controls.Add(lb2, 1, i);
            tlp.Controls.Add(lb3, 2, i);
            tlp.Controls.Add(lb4, 3, i);
            tlp.Controls.Add(tb5, 4, i);
            tlp.Controls.Add(btn6, 5, i);
            tlp.Controls.Add(btn7,6, i);
        }

        tlp.ResumeLayout();
    }
}

Looking at the Reference Source , you can see that Control.ControlCollection.AddRange method is nothing more than a Add loop enclosed in SuspendLayout / ResumeLayout . 查看参考源 ,您可以看到Control.ControlCollection.AddRange方法只不过是SuspendLayout / ResumeLayout包含的Add循环。 Since your code is also enclosed with such calls, there should not be a difference in the performance. 由于您的代码也包含在此类调用中,因此性能不应有差异。

TableLayoutPanel does two additional calls - SetRow and SetColumn , so my first thought was that they are the slow parts. TableLayoutPanel还会执行另外两个调用-SetRowSetColumn ,因此我首先想到的是它们是较慢的部分。 However, looking at the the source code (and measuring the time with or w/o those calls), when the layout engine is suspended, their affect on the performance are negligible. 但是,查看源代码(并测量调用的时间或不进行这些调用的时间),当布局引擎挂起时,它们对性能的影响可以忽略不计。

I did some additional tests with your mcve by not using TableLayoutPanel at all and just adding controls to the form itself. 我根本不使用TableLayoutPanel对您的mcve进行了一些其他测试,而只是向表单本身添加了控件。 The conclusion is - you just have too many controls. 结论是-您的控件太多了。 mcve is creating 4900 controls. mcve正在创建4900个控件。 This is too much for WinForms (and Windows in general). 对于WinForms(通常是Windows)来说,这太多了。 After running it, my Windows almost died. 运行它之后,我的Windows几乎消失了。

So, the add control performance cannot be improved. 因此,添加控制性能无法提高。 But that should not be your main concern. 但这不是您主要关心的问题。 Consider switching to DataGridView or some third party data repeater control which support a lot more number of rows w/o creating significant number of controls. 考虑切换到DataGridView或一些第三方数据转发器控件,这些控件支持很多行,而不会创建大量控件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM