Динамическое заполнение TableLayoutPanel Performance Degredation

У меня есть пользовательский элемент управления, который содержит TableLayoutPanel с двумя столбцами и принимает команды для динамического добавления строк для отображения сведений об элементе, выбранном в отдельном элементе управления. Итак, пользователь выберет строку в другом элементе управления (DataGridView), а в обработчике событий SelectedItemChanged для DataGridView я очищаю элемент управления подробностями, а затем повторно создаю все строки для нового выбранного элемента (который может иметь совершенно разные детали отображение из ранее выбранного элемента). Какое-то время это прекрасно работает. Но если я продолжаю переходить от одного выбранного элемента к другому в течение довольно долгого времени, обновления становятся ОЧЕНЬ медленными (3-5 секунд каждое). Это звучит так, будто я не все утилизирую должным образом, но я не могу понять, что мне не хватает. Вот мой код для очистки TableLayoutPanel:

private readonly List<Control> controls;

public void Clear()
{
    detailTable.Visible = false;
    detailTable.SuspendLayout();
    SuspendLayout();
    detailTable.RowStyles.Clear();
    detailTable.Controls.Clear();
    DisposeAndClearControls();
    detailTable.RowCount = 0;
    detailTable.ColumnCount = 2;
}

private void DisposeAndClearControls()
{
    foreach (Control control in controls)
    {
        control.Dispose();
    }
    controls.Clear();
}

И как только я завершу загрузку всех элементов управления, которые мне нужны, в TableLayoutPanel для следующего отображения подробностей, вот что я называю:

public void Render()
{
    detailTable.ResumeLayout(false);
    detailTable.PerformLayout();
    ResumeLayout(false);
    detailTable.Visible = true;
}

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

Мне были бы интересны любые предложения по повышению производительности рисования, но особенно то, что вызывает ухудшение при множественном выборе.


person Cory McCarty    schedule 24.03.2009    source источник


Ответы (7)


Просто используйте настраиваемый элемент управления, который наследуется от TableLayoutPanel, и установите для свойства DoubleBuffered значение true, отлично работает ... особенно когда вы динамически добавляете или удаляете строки.

public CustomLayout()
{
   this.DoubleBuffered = true;
   InitializeComponent();
}
person Jorge L. Fatta    schedule 18.06.2009
comment
Я только что использовал этот подход в похожем решении, отлично работает. Спасибо - person VikingProgrammer; 23.04.2013

У меня была аналогичная проблема с TableLayout. Если я использовал метод TableLayout.Controls.Clear (), дочерние элементы управления никогда не удалялись, но когда я просто отбрасывал TableLayout, не очищая его, утечка прекращалась. Оглядываясь назад, забавно, что я использовал метод Clear для предотвращения какой-либо утечки.

По-видимому, метод Clear не удаляет элементы управления явно (что имеет смысл, потому что тот факт, что вы удалили их из TableLayout, не означает, что вы закончили с ними), а удаление дочерних элементов управления из TableLayout предотвращает процедуру очистки для удаления потомков, когда сам LayoutTable удаляется (он просто больше о них не знает).

Моя рекомендация: удалите строку detailTable.Controls.Clear ();, удалите сам detailTable из родительской коллекции Controls и удалите ее, а затем создайте новый TableLayout для следующий раунд. Также полностью потеряйте метод DisposeAndClearControls, поскольку он вам не понадобится. По моему опыту, это сработало.

Таким образом, вам больше не придется перерабатывать весь пользовательский элемент управления, а только TableLayout внутри.

person Ishmaeel    schedule 25.02.2010

К сожалению, единственный совет, который я могу предложить, - это позаботиться о размещении элементов управления самостоятельно. По моему опыту, .NET TableLayoutPanel, хотя и очень полезен, ЧТО-ТО дает утечку и становится непривычно медленным по мере роста (и не требуется необоснованного количества ячеек, чтобы добраться до этой точки). Это поведение также можно увидеть в дизайнере.

person Adam Robinson    schedule 24.03.2009
comment
Кажется, ты прав. Если я правильно читаю данные профилировщика VSTS, он большую часть времени проводит в операциях Clear и Visible = true. - person Cory McCarty; 24.03.2009

Я изменил содержащую форму, чтобы просто создавать новую версию моего пользовательского элемента управления при каждом изменении выбора. Он избавляется от старого и строит новый. Кажется, это работает нормально. В любом случае я изначально использовал повторно только один из соображений производительности. Ясно, что это не улучшает производительность. И производительность не будет проблемой, если я избавлюсь от старого и создаю новый.

К сожалению, TableLayoutPanel все же просачивается.

person Cory McCarty    schedule 24.03.2009

Я столкнулся с той же проблемой и нашел хороший способ без особых изменений:

в VB.net

Dim tp As Type = tlpMyPanel.GetType().BaseType
Dim pi As Reflection.PropertyInfo = _
    tp.GetProperty("DoubleBuffered", _ 
    Reflection.BindingFlags.Instance _
    Or Reflection.BindingFlags.NonPublic)
pi.SetValue(tlpMyPanel, True, Nothing)

or in C#:

Type tp = tlpMyPanel.GetType().BaseType;
System.Reflection.PropertyInfo pi = 
    tp.GetProperty("DoubleBuffered",
    System.Reflection.BindingFlags.Instance 
    | System.Reflection.BindingFlags.NonPublic);
pi.SetValue(tlpMyPanel, true, null);
person David    schedule 14.03.2013
comment
Я отправил исправление с откатом, но этот код не компилируется. tlpMyPanel.GetType.BaseType нужны некоторые () .... - person Zyo; 02.08.2017

TableLayoutPanel.Controls.Clear () отлично работает для меня, возможно, потому, что я очищаю его с другой вкладки, чем она отображается в.

person Jay    schedule 04.05.2012

person    schedule
comment
Поздний обзор ответа: пожалуйста, объясните, как и почему это решит описанные проблемы и что это предлагает помимо уже предоставленных ответов. - person Sepster; 01.04.2013