这很简单。
我有一个TableLayoutPanel,它基于数据库查询填充了控件(只是标签,按钮和一些带按钮的面板)。当需要刷新数据时,我使用TableLayoutPanel.Controls.Clear()。不幸的是,这是一个非常缓慢的操作。我希望它比填充表格的代码更快,但速度至少要慢3到4倍。
我明确地证明了缓慢是在执行Controls.Clear()时执行此操作,因为在显示消息框之后执行了对TableLayoutPanel的单一操作(然后过程返回)。控件从下往上明显消失。当记录集用于重新填充TableLayoutPanel时,从上到下显示的控件的速度几乎比我看到的快。
我已经在做TableLayoutPanel.SuspendLayout()和ResumeLayout()。
在表单上使用this.DoubleBuffered = true
似乎没有做任何事情。
我可以通过代码处理整个控件并重新创建它,但这是一个很大的痛苦,并使一个漂亮的表单设计器GUI毫无意义。我将不得不深入研究我在控件上设置的每个属性并为其创建一行代码(虽然我想我可以从设计器代码中获取它,但它仍然感觉不对。)
关于如何更快地完成工作的任何想法?我甚至愿意使用TableLayoutPanel以外的其他方法...我只需要自由地为每个单元格放置多个按钮,或者禁止它能够跨越表格标题中的列。
C#在重绘时能否至少冻结整个表格,然后立即进行全部绘制?
答案 0 :(得分:9)
我也使用TableLayoutPanels来解决速度缓慢的问题。我没有在表单上设置DoubleBuffered属性,而是找到了最好的解决方案,即创建一个继承自TableLayoutPanel的新类,并在该类的构造函数中启用双缓冲:
public class DoubleBufferedTableLayoutPanel : TableLayoutPanel
{
public DoubleBufferedTableLayoutPanel()
{
DoubleBuffered = true;
}
}
然后,在通常使用TableLayoutPanel的地方使用DoubleBufferedTableLayoutPanel。
答案 1 :(得分:3)
这似乎适用于我的用途:
tableLayoutPanel.Visible = false;
tableLayoutPanel.Clear();
/* Add components to it */
tableLayoutPanel.Visible = true;
答案 2 :(得分:3)
没有必要像Chris Ryan's answer中那样继承TableLayoutPanel
。我遇到了同样的问题,并通过反射设置属性来解决它:
typeof(TableLayoutPanel)
.GetProperty("DoubleBuffered",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.SetValue(myTableLayoutPanel, true, null);
答案 3 :(得分:0)
如果我要建立一些动态的gui,我总是会在代码中这样做。但是在起点上我只是从设计师的虚拟形式和风格开始,每个控制方式我(或更好的客户)喜欢。然后我查看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
等小控件开始,然后转到GroupBox
或TableLayoutPanel
等容器。
在某些情况下,这会导致工厂函数调用其他几个工厂函数。如果这变得正确,那么就应该考虑将这些控件封装到单个UserControl
中,但是如果需要或者不这样,它总是它取决于。
在我身边,我只能鼓励你将代码从设计器中移到自编写的函数中。一开始它(一如既往)更多的工作,但之后更容易对布局做出更大的改变。