Winforms
C#
TableLayoutPanel
programming
UI design

Winforms TableLayoutPanel adding rows programmatically

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

TableLayoutPanel is one of the most practical layout containers in WinForms when a form needs to grow dynamically. Adding rows programmatically is straightforward once you understand that the panel tracks both RowCount and RowStyles, and those two pieces need to stay in sync.

The Basic Pattern

To add a new row, you normally do three things:

  • increase RowCount
  • add a matching RowStyle
  • place controls into the new row with Controls.Add

Here is a simple reusable helper:

csharp
1using System.Windows.Forms;
2
3public static class TableLayoutHelpers
4{
5    public static int AddRow(TableLayoutPanel table, params Control[] controls)
6    {
7        int row = table.RowCount;
8        table.RowCount += 1;
9        table.RowStyles.Add(new RowStyle(SizeType.AutoSize));
10
11        for (int column = 0; column < controls.Length && column < table.ColumnCount; column++)
12        {
13            table.Controls.Add(controls[column], column, row);
14        }
15
16        return row;
17    }
18}

If the panel already has the right number of columns, this is enough for simple form-like layouts.

Building a Row with Controls

The most common case is adding a label and an editor control together.

csharp
1using System.Windows.Forms;
2
3public partial class MainForm : Form
4{
5    public MainForm()
6    {
7        InitializeComponent();
8
9        tableLayoutPanel1.ColumnCount = 2;
10        tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 35f));
11        tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 65f));
12
13        AddPersonRow("Name", "Ada Lovelace");
14        AddPersonRow("Role", "Analyst");
15    }
16
17    private void AddPersonRow(string caption, string value)
18    {
19        var label = new Label
20        {
21            Text = caption,
22            AutoSize = true,
23            Anchor = AnchorStyles.Left
24        };
25
26        var textBox = new TextBox
27        {
28            Text = value,
29            Dock = DockStyle.Fill
30        };
31
32        TableLayoutHelpers.AddRow(tableLayoutPanel1, label, textBox);
33    }
34}

Using DockStyle.Fill or suitable Anchor values matters. Without them, the controls may not resize correctly when the form grows.

Inserting Many Rows Efficiently

If you add several rows at once, suspend layout first. That avoids repeated layout passes and reduces flicker.

csharp
1tableLayoutPanel1.SuspendLayout();
2
3for (int i = 0; i < 10; i++)
4{
5    AddPersonRow($"Field {i + 1}", $"Value {i + 1}");
6}
7
8tableLayoutPanel1.ResumeLayout();

This is a small change, but it makes dynamic forms feel much cleaner.

Removing Rows

Adding rows is only half the job. If your UI is editable, you often need to remove a row safely too. That means removing the controls in that row, disposing them, and then keeping layout metadata consistent.

csharp
1using System.Linq;
2using System.Windows.Forms;
3
4public static void RemoveLastRow(TableLayoutPanel table)
5{
6    if (table.RowCount == 0)
7        return;
8
9    int row = table.RowCount - 1;
10
11    var controls = table.Controls
12        .Cast<Control>()
13        .Where(c => table.GetRow(c) == row)
14        .ToList();
15
16    foreach (var control in controls)
17    {
18        table.Controls.Remove(control);
19        control.Dispose();
20    }
21
22    if (table.RowStyles.Count > row)
23        table.RowStyles.RemoveAt(row);
24
25    table.RowCount -= 1;
26}

If you only decrement RowCount without cleaning up the controls, the layout and control collection drift apart.

Choosing the Right Row Style

AutoSize is a good default for content-driven rows. Use Absolute when every row should have the same fixed height, and use Percent more carefully because percentage-based rows can interact in surprising ways once dynamic content enters the layout.

For most programmatically added form rows:

  • 'AutoSize works best for labels and text boxes'
  • 'Absolute is useful for uniform button rows'
  • 'Percent is usually better for high-level sections than for repeated input rows'

Common Pitfalls

  • Increasing RowCount without adding a matching RowStyle. The UI may render unpredictably.
  • Adding controls without setting Dock or Anchor, which leaves them badly sized when the form changes.
  • Forgetting to call SuspendLayout and ResumeLayout during batch updates.
  • Removing rows by count only and leaving old controls behind in the panel.

Summary

  • Add rows by updating both RowCount and RowStyles.
  • Place controls with Controls.Add(control, column, row).
  • Use AutoSize for most dynamic form rows.
  • Suspend layout during bulk row updates for smoother rendering.
  • When removing rows, clean up both the controls and the row style metadata.

Course illustration
Course illustration

All Rights Reserved.