.Net TableLayoutPanel –清除控件非常慢
这真的很简单。
我有一个 TableLayoutPanel,其中填充了基于数据库查询的控件(仅标签、按钮和一些带有按钮的面板)。当需要刷新数据时,我使用TableLayoutPanel.Controls.Clear()。不幸的是,这是一个非常慢的操作。我希望它比填充表的代码更快,但它至少慢 3 或 4 倍。
我明确地证明了缓慢是在执行 Controls.Clear() 时执行的,方法是将其作为显示消息框后对 TableLayoutPanel 执行的单一操作(然后过程返回)。控件明显从下往上消失。当使用记录集重新填充TableLayoutPanel时,控件从上到下出现的速度几乎比我看到的要快。
我已经在做 TableLayoutPanel.SuspendLayout() 和 ResumeLayout() 了。
在表单上使用 this.DoubleBuffered = true 似乎没有任何作用。
我可以处理整个控件并通过代码重新创建它,但这是一个很大的痛苦,并且使得良好的表单设计器 GUI 变得毫无意义。我必须深入研究我在控件上设置的每个属性并为其创建一行代码(尽管我想我可以从设计器代码本身中得到它,但它仍然感觉错误)。
关于如何更快地完成工作有什么想法吗?我什至愿意使用除 TableLayoutPanel 之外的其他方法...我只需要自由地在每个单元格中放置多个按钮,或者禁止它能够跨越表标题中的列。
C# 至少可以在重绘时冻结整个表单,然后一次性绘制所有内容吗?
This is really simple.
I have a TableLayoutPanel that is populated with controls (just Labels, Buttons, and some Panels with buttons) based on a database query. When the data needs to be refreshed, I use TableLayoutPanel.Controls.Clear(). Unfortunately, this is a very slow operation. I would expect it to be faster than the code populating the table, but it is at least 3 or 4 times slower.
I definitively proved that the slowness is when executing Controls.Clear() by executing this as the single thing done to the TableLayoutPanel after a message box is displayed (then the procedure returns). The controls visibly disappear from the bottom up. When the recordset is used to repopulate the TableLayoutPanel, the speed of the controls appearing from top to bottom is almost faster than I can see.
I'm already doing TableLayoutPanel.SuspendLayout() and ResumeLayout().
Using this.DoubleBuffered = true
on the form doesn't appear to do anything.
I could just Dispose the entire control and recreate it through code, but this is a big pain and makes having a nice form designer GUI pointless. I would have to dig into every property I've set on the control and create a line of code for it (though I guess I could get this out of the designer code itself, it still feels wrong).
Any ideas on how to do the job faster? I'm even open to using other methods besides a TableLayoutPanel... I just need the freedom to put multiple buttons per cell or barring that to be able to span columns in the table header.
Can C# at least freeze the whole form while it redraws and then paint all at once?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我也遇到了使用 TableLayoutPanels 速度缓慢的问题。我发现的最佳解决方案不是在表单上设置 DoubleBuffered 属性,而是创建一个继承自 TableLayoutPanel 的新类,并在该类的构造函数中启用双缓冲:
然后,在通常使用 DoubleBufferedTableLayoutPanel 的地方使用 DoubleBufferedTableLayoutPanel表布局面板。
I've run into issues with slowness using TableLayoutPanels as well. Rather than setting the DoubleBuffered property on the form, the best solution I have found is to create a new class that inherits from TableLayoutPanel, and in that class' constructor, enable double-buffering:
Then, use the DoubleBufferedTableLayoutPanel wherever you would normally use a TableLayoutPanel.
这似乎适合我的用途:
This seems to work for my uses:
无需像 Chris Ryan 的回答 那样对
TableLayoutPanel
进行子类化。我遇到了同样的问题并通过反射设置属性解决了它:There is no need to subclass
TableLayoutPanel
as in Chris Ryan's answer. I had the same problem and solved it by setting the property through reflection:如果我要构建一些动态 GUI,我总是会在代码中这样做。但一开始,我只是从设计师那里开始一个虚拟的表单和样式,每个控件都按照我(或者更好的是客户)喜欢的方式进行控制。然后,我查看 Designer.cs 文件,并将必要的属性设置从其中复制到某些工厂函数中,例如
,因此我确保每个控件在 GUI 上的感觉和外观都相同。这将在我的界面中的每个级别上完成(从
TextBox
等小控件开始,一直到GroupBox
或TableLayoutPanel
等容器。在某些情况下,这会导致工厂函数调用其他几个工厂函数,如果这种情况成为现实,那么是时候考虑将这些控件封装到单个 UserControl 中了,但一如既往。取决于是否需要。
从我的角度来看,我只能鼓励您将代码从设计器中移出到自己编写的函数中,一开始(一如既往)需要更多工作,但之后就可以了。更容易对布局进行更大的更改。
If i'm going to built up some dynamic gui i'm always going to do so in code. But at a starting point i just start with the designer on a dummy form and style each control the way i (or better the customer) like(s). Afterwards i take a look into the Designer.cs file and copy the necessary property settings out of it into some factory function like
So i make sure that every control feels and looks the same on my GUI. This will be done on each level within my surface (starting with the small controls like
TextBox
and goes up to the containers likeGroupBox
orTableLayoutPanel
.In some cases this leads to a point where a factory function calls several other factory functions. If this is becoming true it's time to think about encapsulating these controls into a single
UserControl
, but as always it depends if this is needed or not.From my side i can only encourage you to move your code out of the designer into a self-written function. At the beginning it is (as always) more work, but afterwards it is easier to make even bigger changes to the layout.