2010-07-26 14 views
7

To jest naprawdę proste..Net TableLayoutPanel - Kontrola usuwania jest bardzo powolna

Mam TableLayoutPanel, który jest wypełniony formantów (tylko etykiety, przyciski i niektóre panele z przyciskami) na podstawie kwerendy bazy danych. Gdy dane wymagają odświeżenia, używam TableLayoutPanel.Controls.Clear(). Niestety, jest to bardzo powolna operacja. Spodziewam się, że będzie on szybszy niż kod wypełniający tabelę, ale jest co najmniej 3 lub 4 razy wolniejszy.

Zdecydowanie udowodniłem, że powolność jest wykonywana podczas wykonywania Controls.Clear(), wykonując to jako pojedynczą czynność wykonaną w TableLayoutPanel po wyświetleniu okna komunikatu (procedura powraca). Kontrolki wyraźnie znikają z dołu do góry. Kiedy zestaw rekordów jest używany do ponownego zaludnienia TableLayoutPanel, szybkość elementów sterujących pojawiających się od góry do dołu jest prawie szybsza niż widzę.

Już robię TableLayoutPanel.SuspendLayout() i ResumeLayout().

W formularzu nie wydaje się, aby cokolwiek zrobić.

Mogę po prostu usunąć całą kontrolę i odtworzyć ją za pomocą kodu, ale to jest wielki ból i sprawia, że ​​niezły projekt GUI jest bezcelowy. Musiałbym zagłębić się w każdą nieruchomość, którą ustawiłem na kontrolerze i stworzyć dla niej kod (choć wydaje mi się, że mógłbym to wydostać z samego kodu projektanta, nadal jest źle).

Jakieś pomysły na to, jak wykonać zadanie szybciej? Jestem nawet otwarty na używanie innych metod poza TableLayoutPanel ... Po prostu potrzebuję wolności do umieszczenia wielu przycisków na komórkę lub zakazu, aby móc rozciągnąć kolumny w nagłówku tabeli.

Czy C# może przynajmniej zamrozić cały formularz, gdy odrysowuje, a następnie maluje wszystkie naraz?

+0

Wspominasz TableLayoutPanel i FlowLayoutPanel. –

+0

Czy uruchomiłeś profiler, aby udowodnić, że jest to dokładnie jedna linia kodu? Czy możliwe jest wywołanie skutków ubocznych w tym wierszu kodu? Zdarzenia, które są wywoływane, aby sterowanie stało się niewidoczne lub podobne? – WillfulWizard

+0

@Willfulwizard Zaktualizowałem swój post z powodu, dla którego uważam, że to Controls.Clear() zajmuje dużo czasu. – ErikE

Odpowiedz

9

Wystąpiłem również problemy z powolnością za pomocą TableLayoutPanels również.Zamiast ustawiać właściwość DoubleBuffered na formularzu, najlepszym rozwiązaniem znalazłem jest stworzenie nowej klasy, która dziedziczy TableLayoutPanel iw tej klasie konstruktora, włącz podwójne buforowanie:

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

Następnie użyj DoubleBufferedTableLayoutPanel, gdziekolwiek normalnie używasz TableLayoutPanel.

+0

Czy możesz spekulować, dlaczego tak uważasz? TableLayoutPanel ma własność DoubleBuffered ... dlaczego nie ustawić jej po prostu na czas projektowania (zakładam, że to nie działa)? Więc jaka jest umowa? – ErikE

+1

W wersji .NET używam (2008, SP1), ani pasek narzędzi Właściwości ani Intellisense nie wyświetla właściwości DoubleBuffered dla TableLayoutPanels. Jeśli masz instancję TableLayoutPanel, powiedz myTableLayoutPanel i spróbuj ustawić myTableLayoutPanel.DoubleBuffered = true, kompilator wyświetli błąd "Nie można uzyskać dostępu do chronionego elementu" System.Windows.Forms.Control.DoubleBuffered ". Jeśli twoja wersja .NET rzeczywiście oferuje właściwość DoubleBuffered na zwykłym TableLayoutPanel, to wyobrażam sobie, że ustawienie tam będzie działało dobrze. –

+0

Muszę powiedzieć, że nigdy nie spodziewałem się, że będę musiał robić tego rodzaju poprawki, nie mówiąc już o tym, żeby mieć wpływ na wydajność w tak zdumiewająco pozytywny sposób. Schludne rzeczy! – xDisruptor

0

Jeśli mam zamiar zbudować jakieś dynamiczne gui, zawsze będę to robić w kodzie. Ale w punkcie wyjścia zaczynam od projektanta w formie fikcyjnej i stylizuję każdy sposób w taki sam sposób, jak ja (lub lepszy klient). I potem spójrz do pliku Designer.cs i skopiować niezbędne ustawienia właściwości z nim do jakiejś funkcji fabrycznego jak

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

Więc upewnij się, że każda kontrola czuje i wygląda tak samo na moim GUI. Nastąpi to na każdym poziomie w moim powierzchni (począwszy od małych kontroli, takich jak TextBox i idzie do pojemników, takich jak GroupBox lub TableLayoutPanel.

W niektórych przypadkach prowadzi to do punktu, w którym funkcja fabryka nazywa kilka innych funkcji fabrycznych . Jeśli ta staje się prawdą, że nadszedł czas, aby myśleć o enkapsulacji tych elementów sterujących w jednym UserControl, ale jak zawsze zależy jeśli jest to potrzebne, czy nie.

z mojej strony mogę tylko zachęcić, aby przenieść swój kod na zewnątrz projektanta w funkcję napisaną samodzielnie, na początku jest (jak zawsze) więcej pracy, ale później łatwiej jest zrobić jeszcze większy cha zbliża się do układu.

3

To wydaje się działać dla moich zastosowań:

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

Nie ma potrzeby do podklasy TableLayoutPanel jak w Chris Ryan's answer. Miałem ten sam problem i rozwiązałem go, ustawiając właściwość poprzez odbicie:

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