Dynamically populated performance table TableLayoutPanel

I have a user control that contains 2 columns of TableLayoutPanel and accepts commands to dynamically add rows to display the details of the element selected in a separate control. Thus, the user will select a row in another control (DataGridView), and in the SelectedItemChanged event handler for the DataGridView, I clear the detail control and then regenerate all the rows for the new selected element (which may have completely different details displaying from the previously selected element) . This has been working fine for a while. But if I continue to move from one selected item to another for quite some time, updates become VERY slow (3-5 seconds each). It sounds like I'm not managing everything right, but I can't understand what I am missing. Here is my code to clear 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(); } 

And as soon as I finish loading all the controls that I want in the TableLayoutPanel, for the next detailed display here, what I call:

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

I use nothing but shortcuts (and TextBox very rarely) inside the TableLayoutPanel, and add shortcuts and text fields to the list of controls (link to DisposeAndClearControls ()) when I create them. I tried just iterating over the details. Controls and removes them in this way, but it seems that it skips half of the controls (determined by going through it to the debugger). So I know that I am all of them.

I would be interested in any suggestions for improving the performance of the drawing, but especially what caused the degradation of several options.

+4
source share
7 answers

I changed the containing form to just build a new version of my user control every time I make a selection. He uses the old and creates a new one. This seems to be fine. In any case, I initially left with reusing just one of the performance considerations. Obviously, this does not improve performance. And performance is not a problem if I use the old one and create a new one.

Unfortunately, the TableLayoutPanel is leaking like this.

+1
source

Just use a custom control that inherits from TableLayoutPanel and sets the DoubleBuffered property to true, works fine ... especially when you dynamically add or delete rows.

 public CustomLayout() { this.DoubleBuffered = true; InitializeComponent(); } 
+10
source

I had a similar problem with TableLayout. If I used the TableLayout.Controls.Clear () method, the child controls were not deleted, but when I just reset TableLayout without cleaning it, the leak stopped. Looking back, it’s funny that I used the Clear method to prevent leakage.

Obviously, the Clear method does not explicitly use the controls (which makes sense, since the fact that you removed them from TableLayout does not mean that you dealt with them) and removing the child controls from TableLayout prevents the cleanup procedure from getting rid of children when LayoutTable itself will be deleted (it just doesn't know about them anymore).

My recommendation: remove the detailTable.Controls.Clear () line; , remove the most detailed table from the parent Controls collection and delete it, then create a new TableLayout for the next round. Also completely lose the DisposeAndClearControls method, since you will not need it. In my experience, this worked well.

This way, you no longer have to rework the entire user control, but only the TableLayout inside.

+4
source

I ran into the same problem and found a good way without changing too much:

at 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); 
+1
source

Unfortunately, the only advice I can offer is taking care of placing your controls yourself. In my experience, the .NET TableLayoutPanel, although very useful, leaks SOMETHING and becomes unusually slow when it grows (and this also does not require an unreasonable number of cells). This behavior can be seen in the designer.

0
source

TableLayoutPanel.Controls.Clear () works fine for me, perhaps because I clear it from a different tab than its displayed.

0
source
 List<Control> controls = new List<Control>(); foreach (Control control in tableLayoutPanelEnderecoDetalhes.Controls) { controls.Add(control); } foreach (Control control in controls) { control.Dispose(); } 
0
source

All Articles