将控件添加到 TableLayoutPanel 的快速方法
Fast way to add Controls to a TableLayoutPanel
我必须向 TableLayoutPanel
动态添加大量 Control
对象,这需要花费大量时间。我还需要能够通过 TableLayoutPanel
的行索引和列索引访问控件,反之亦然。
TableLayoutPanel.Controls
有(据我所知)3 种添加 Control
对象的方法:
.Add(Control)
- 继承,位置为 -1,-1 与 .GetCellPosition(Control)
.Add(Control, column, row)
- 位置和索引正确,但可能有点慢?
.AddRange (Control[])
- 继承,更快,显示的位置是正确的(每个单元格都被填充,如果需要,之后设置列跨度),但位置是 -1,-1 .GetCellPosition(Control)
有没有办法结合 .Add(Control, column, row
和 .AddRange(Control[])
的优点,即将大量 Control
对象快速添加到 TableLayoutPanel
,同时仍然能够以编程方式获取 Control
的位置?
编辑 以包含评论中的一些信息:
- 最多添加了 1000 个控件
- 我已经在使用
SuspendLayout()
和 ResumeLayout()
TableLayoutPanel
加载大约需要 2 秒。根据分析器,大约 50% 的时间用于添加控件,20% 用于 ResumeLayout()
编辑:MCVE
我的原始代码更复杂,但这是一个 TableLayoutPanel
的示例,其中添加控件花费了大部分时间 (2/3)。我正在寻找一种方法来加快速度。
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();
}
}
查看Reference Source,您可以看到Control.ControlCollection.AddRange
方法只不过是SuspendLayout
/ ResumeLayout
中包含的Add
循环。由于您的代码也包含在此类调用中,因此性能应该没有差异。
TableLayoutPanel
进行了两次额外的调用 - SetRow and SetColumn,所以我的第一个想法是它们是缓慢的部分。但是,查看源代码(并测量使用或 w/o 这些调用的时间),当布局引擎暂停时,它们对性能的影响可以忽略不计。
我对您的 mcve
做了一些额外的测试,完全不使用 TableLayoutPanel
,只是将控件添加到表单本身。结论是——你的控件太多了。 mcve
正在创建 4900 个控件。这对于 WinForms(通常 Windows)来说太多了。在 运行 它之后,我的 Windows 差点死了。
所以,添加控件的性能无法提升。但这不应该是您主要关心的问题。考虑切换到 DataGridView
或某些支持更多行的第三方数据转发器控件 w/o 创建大量控件。
我必须向 TableLayoutPanel
动态添加大量 Control
对象,这需要花费大量时间。我还需要能够通过 TableLayoutPanel
的行索引和列索引访问控件,反之亦然。
TableLayoutPanel.Controls
有(据我所知)3 种添加 Control
对象的方法:
.Add(Control)
- 继承,位置为 -1,-1 与.GetCellPosition(Control)
.Add(Control, column, row)
- 位置和索引正确,但可能有点慢?.AddRange (Control[])
- 继承,更快,显示的位置是正确的(每个单元格都被填充,如果需要,之后设置列跨度),但位置是 -1,-1.GetCellPosition(Control)
有没有办法结合 .Add(Control, column, row
和 .AddRange(Control[])
的优点,即将大量 Control
对象快速添加到 TableLayoutPanel
,同时仍然能够以编程方式获取 Control
的位置?
编辑 以包含评论中的一些信息:
- 最多添加了 1000 个控件
- 我已经在使用
SuspendLayout()
和ResumeLayout()
TableLayoutPanel
加载大约需要 2 秒。根据分析器,大约 50% 的时间用于添加控件,20% 用于ResumeLayout()
编辑:MCVE
我的原始代码更复杂,但这是一个 TableLayoutPanel
的示例,其中添加控件花费了大部分时间 (2/3)。我正在寻找一种方法来加快速度。
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();
}
}
查看Reference Source,您可以看到Control.ControlCollection.AddRange
方法只不过是SuspendLayout
/ ResumeLayout
中包含的Add
循环。由于您的代码也包含在此类调用中,因此性能应该没有差异。
TableLayoutPanel
进行了两次额外的调用 - SetRow and SetColumn,所以我的第一个想法是它们是缓慢的部分。但是,查看源代码(并测量使用或 w/o 这些调用的时间),当布局引擎暂停时,它们对性能的影响可以忽略不计。
我对您的 mcve
做了一些额外的测试,完全不使用 TableLayoutPanel
,只是将控件添加到表单本身。结论是——你的控件太多了。 mcve
正在创建 4900 个控件。这对于 WinForms(通常 Windows)来说太多了。在 运行 它之后,我的 Windows 差点死了。
所以,添加控件的性能无法提升。但这不应该是您主要关心的问题。考虑切换到 DataGridView
或某些支持更多行的第三方数据转发器控件 w/o 创建大量控件。