.Net TableLayoutPanel – 清除控件非常慢

这很简单。

我有一个基于数据库查询填充控件(只是标签,按钮和一些带按钮的面板)的TableLayoutPanel。 当需要刷新数据时,我使用TableLayoutPanel.Controls.Clear()。 不幸的是,这是一个非常缓慢的操作。 我希望它比填充表格的代码更快,但它至少要慢3到4倍。

我明确地certificate了缓慢是在执行Controls.Clear()时执行此操作,因为在显示消息框之后对TableLayoutPanel执行了一次操作(然后程序返回)。 控制从底部向上明显消失。 当记录集用于重新填充TableLayoutPanel时,从上到下出现的控件的速度几乎比我看到的要快。

我已经在做TableLayoutPanel.SuspendLayout()和ResumeLayout()。

在窗体上使用this.DoubleBuffered = true似乎没有做任何事情。

我可以通过代码处理整个控件并重新创建它,但这是一个很大的痛苦,并使一个漂亮的表单设计器GUI毫无意义。 我将不得不深入研究我在控件上设置的每个属性并为其创建一行代码(虽然我想我可以从设计器代码本身中获取它,但它仍然感觉不对)。

关于如何更快地完成工作的任何想法? 我甚至愿意使用除TableLayoutPanel之外的其他方法…我只需要自由地为每个单元格放置多个按钮或禁止它能够跨越表头中的列。

C#在重绘时能否至少冻结整个表格,然后一次全部绘制?

我也使用TableLayoutPanels来解决速度缓慢的问题。 我没有在表单上设置DoubleBuffered属性,而是找到了最好的解决方案,即创建一个inheritance自TableLayoutPanel的新类,并在该类的构造函数中启用双缓冲:

 public class DoubleBufferedTableLayoutPanel : TableLayoutPanel { public DoubleBufferedTableLayoutPanel() { DoubleBuffered = true; } } 

然后,在通常使用TableLayoutPanel的任何地方使用DoubleBufferedTableLayoutPanel。

这似乎适用于我的用途:

 tableLayoutPanel.Visible = false; tableLayoutPanel.Clear(); /* Add components to it */ tableLayoutPanel.Visible = true; 

在Chris Ryan的回答中,没有必要将TableLayoutPanel子类化。 我有同样的问题,通过reflection设置属性解决了它:

 typeof(TableLayoutPanel) .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) .SetValue(myTableLayoutPanel, true, null); 

如果我要建立一些动态的gui,我总是会在代码中这样做。 但是在起点上,我只是从设计师的虚拟forms和风格开始,每个控制方式我(或更好的客户)喜欢。 然后我查看Designer.cs文件并将必要的属性设置复制到一些工厂函数中

 private TextBox CreateTextBox(string name, /* maybe other parameters */) { var textBox = new TextBox(); textBox.Name = name; //Other settings from given parameters... //Further settings which are all the same for these kind of control textBox.KeyDown += (sender, e) => {}; return textBox; } 

所以我确保每个控件在我的GUI上都感觉和看起来一样。 这将在我的表面中的每个级别上完成(从像TextBox这样的小控件开始,然后转到像GroupBoxTableLayoutPanel这样的容器。

在某些情况下,这会导致工厂函数调用其他几个工厂函数。 如果这成为现实,那么可以考虑将这些控件封装到单个UserControl ,但是一如既往, 它取决于是否需要。

在我这边,我只能鼓励你将你的代码从设计师中移到一个自编的函数中。 一开始它(一如既往)更多的工作,但之后更容易对布局做出更大的改变。