.Net TableLayoutPanel –清除控件非常慢

发布于 2024-09-11 16:11:31 字数 705 浏览 5 评论 0原文

这真的很简单。

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光沙漏 2024-09-18 16:11:31

我也遇到了使用 TableLayoutPanels 速度缓慢的问题。我发现的最佳解决方案不是在表单上设置 DoubleBuffered 属性,而是创建一个继承自 TableLayoutPanel 的新类,并在该类的构造函数中启用双缓冲:

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

然后,在通常使用 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:

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

Then, use the DoubleBufferedTableLayoutPanel wherever you would normally use a TableLayoutPanel.

鱼窥荷 2024-09-18 16:11:31

这似乎适合我的用途:

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

This seems to work for my uses:

tableLayoutPanel.Visible = false;
tableLayoutPanel.Clear();
/* Add components to it */
tableLayoutPanel.Visible = true;
望笑 2024-09-18 16:11:31

无需像 Chris Ryan 的回答 那样对 TableLayoutPanel 进行子类化。我遇到了同样的问题并通过反射设置属性解决了它:

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

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:

typeof(TableLayoutPanel)
   .GetProperty("DoubleBuffered",
      System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
   .SetValue(myTableLayoutPanel, true, null);
郁金香雨 2024-09-18 16:11:31

如果我要构建一些动态 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 等小控件开始,一直到 GroupBoxTableLayoutPanel 等容器。

在某些情况下,这会导致工厂函数调用其他几个工厂函数,如果这种情况成为现实,那么是时候考虑将这些控件封装到单个 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

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;
}

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 like GroupBox or TableLayoutPanel.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文