.Net TableLayoutPanel - Очистка элементов управления очень медленная - PullRequest
7 голосов
/ 27 июля 2010

Это действительно просто.

У меня есть TableLayoutPanel, которая заполняется элементами управления (только метки, кнопки и некоторые панели с кнопками) на основе запроса к базе данных.Когда необходимо обновить данные, я использую TableLayoutPanel.Controls.Clear ().К сожалению, это очень медленная операция.Я ожидал бы, что это будет быстрее, чем код, заполняющий таблицу, но это по крайней мере в 3 или 4 раза медленнее.

Я окончательно доказал, что медлительность происходит при выполнении Controls.Clear (), выполнив это какодна вещь, сделанная для TableLayoutPanel после отображения окна сообщения (затем процедура возвращается).Органы управления заметно исчезают снизу вверх.Когда набор записей используется для повторного заполнения TableLayoutPanel, скорость элементов управления, появляющихся сверху вниз, почти выше, чем я вижу.

Я уже делаю TableLayoutPanel.SuspendLayout () и ResumeLayout ().

Использование this.DoubleBuffered = true в форме, похоже, ничего не делает.

Я мог бы просто избавиться от всего элемента управления и воссоздать его через код, но это большая боль и делает приятнымДизайнер форм GUI бессмыслен.Мне нужно было бы покопаться в каждом свойстве, которое я установил для элемента управления, и создать для него строку кода (хотя я думаю, что я мог бы извлечь это из самого кода конструктора, он все еще чувствует себя неправильно).

Любые идеи о том, как сделать работу быстрее?Я даже открыт для использования других методов, кроме TableLayoutPanel ... Мне просто нужна свобода, чтобы поместить несколько кнопок на ячейку или запрет, чтобы иметь возможность охватывать столбцы в заголовке таблицы.

Может ли C # хотя бызаморозить всю форму, пока она перерисовывается, а затем рисовать все сразу?

Ответы [ 4 ]

9 голосов
/ 12 октября 2010

Я также столкнулся с проблемами с медлительностью, используя TableLayoutPanels.Вместо того, чтобы задавать свойство DoubleBuffered в форме, лучшее решение, которое я нашел, - это создать новый класс, который наследует от TableLayoutPanel, и в конструкторе этого класса включить двойную буферизацию:

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

Затем,используйте DoubleBufferedTableLayoutPanel везде, где вы обычно используете TableLayoutPanel.

3 голосов
/ 10 февраля 2015

Нет необходимости создавать подкласс TableLayoutPanel, как в Крис Райан .У меня была та же проблема, и я решил ее, задав свойство через отражение:

typeof(TableLayoutPanel)
   .GetProperty("DoubleBuffered",
      System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
   .SetValue(myTableLayoutPanel, true, null);
3 голосов
/ 15 апреля 2012

Это, кажется, работает для моих целей:

tableLayoutPanel.Visible = false;
tableLayoutPanel.Clear();
/* Add components to it */
tableLayoutPanel.Visible = true;
0 голосов
/ 11 августа 2010

Если я собираюсь создать динамический графический интерфейс, я всегда буду делать это в коде. Но в начале я просто начинаю с дизайнера на фиктивной форме и стилизую каждый элемент управления так, как мне (или лучше клиенту) нравится (с). После этого я заглядываю в файл 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;
}

Так что я уверен, что каждый элемент управления выглядит и выглядит одинаково в моем графическом интерфейсе. Это будет сделано на каждом уровне моей поверхности (начиная с небольших элементов управления, таких как TextBox и заканчивая контейнерами, такими как GroupBox или TableLayoutPanel.

В некоторых случаях это приводит к тому, что заводская функция вызывает несколько других заводских функций. Если это становится правдой, пришло время подумать о инкапсуляции этих элементов управления в один UserControl, но, как всегда , зависит , нужно это или нет.

Со своей стороны, я могу только побудить вас переместить свой код из конструктора в самописную функцию. В начале это (как всегда) больше работы, но потом легче внести еще большие изменения в макет.

...