2010-07-26 30 views
7

這非常簡單。.Net TableLayoutPanel - 清除控件非常慢

我有一個基於數據庫查詢填充了控件(只是標籤,按鈕,和一些面板的按鈕)的TableLayoutPanel。當數據需要刷新時,我使用TableLayoutPanel.Controls.Clear()。不幸的是,這是一個非常緩慢的操作。我希望它比填充表格的代碼快,但速度至少要慢3到4倍。

我明確證明,執行Controls.Clear()時,執行此操作時,會顯示一個消息框(然後過程返回),以此作爲單個事件對TableLayoutPanel執行操作。控件明顯從底部消失。當記錄集用於重新填充TableLayoutPanel時,從上到下顯示的控件的速度幾乎快於我看到的速度。

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

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

我可以放棄整個控件並通過代碼重新創建它,但這是一個很大的痛苦,並且使得一個漂亮的表單設計器GUI沒有意義。我將不得不深入挖掘每一個我在控件上設置的屬性,併爲它創建一行代碼(儘管我想我可以從設計器代碼本身中獲得它,但仍然感覺錯誤)。

關於如何更快地完成這項工作的任何想法?我甚至可以使用除TableLayoutPanel之外的其他方法...我只需要在每個單元格中放置多個按鈕的自由度,或者限制它可以跨越表格標題中的列。

C#至少可以凍結整個表單並重繪,然後一次全部繪製完成?

+0

您提到TableLayoutPanel和FlowLayoutPanel。 – 2010-07-26 22:07:06

+0

你運行一個分析器來證明它確切的那一行代碼?這行代碼是否可能會導致副作用?被稱爲控件的事件被隱藏起來或類似的東西? – WillfulWizard 2010-07-26 22:21:17

+0

@Willfulwizard我更新了我的帖子,之所以我認爲這是需要很長時間的Controls.Clear()。 – ErikE 2010-07-27 00:50:32

回答

9

我也遇到了使用TableLayoutPanels的慢度問題。而不是設置窗體上的DoubleBuffered財產,我已經找到了最好的解決方案是創建一個從TableLayoutPanel中繼承了一個新的類,並且在類的構造函數,啓用雙緩衝:

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

然後,使用DoubleBufferedTableLayoutPanel,無論你通常使用TableLayoutPanel。

+0

你可以推測你爲什麼這麼認爲? TableLayoutPanel有一個DoubleBuffered屬性,它本身...爲什麼不在設計時設置它(我假設這不起作用)?那麼交易是什麼? – ErikE 2010-10-12 22:31:47

+1

在我使用的.NET版本(2008,SP1)中,屬性工具欄和Intellisense都沒有列出TableLayoutPanels的DoubleBuffered屬性。如果你有一個TableLayoutPanel的實例,比如myTableLayoutPanel,並試圖設置myTableLayoutPanel.DoubleBuffered = true,編譯器將顯示「無法訪問受保護的成員'System.Windows.Forms.Control.DoubleBuffered'」錯誤。如果你的.NET版本確實在普通的TableLayoutPanel上提供了DoubleBuffered屬性,那麼我會想象在那裏設置它會正常工作。 – 2010-10-13 15:22:44

+0

我不得不說,我從來沒有想過必須進行這種調整,更不用說它會以如此驚人的積極方式影響性能。整潔的東西! – xDisruptor 2016-07-14 20:47:08

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小控件和上升到像GroupBoxTableLayoutPanel容器。

在某些情況下,這導致了一個點,一個工廠函數調用其他幾個工廠函數如果這是成爲真正的它的時間去思考這些控件封裝成一個單一的UserControl,但始終這取決於如果這是需要與否。

從我的身邊,我只能鼓勵你了移動代碼的設計師變成一種自我寫作的功能,開始時(一如既往)做更多的工作,但之後更容易製作更大的茶年齡的佈局。

3

這似乎爲我工作的用途:

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

有沒有需要繼承TableLayoutPanelChris Ryan's answer。我有同樣的問題,並通過反射設置屬性來解決它:

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