删除 TableLayoutPanel 中的 Row 会导致布局问题布局、问题、TableLayoutPanel、Row

2023-09-09 21:09:48 作者:陪你到地球毁灭

我有一个带有 TableLayoutPanel 的 WinForms 应用程序;这是定义代码:

tableLayoutPanel1 = new TableLayoutPanel();tableLayoutPanel1.Dock = DockStyle.Fill;tableLayoutPanel1.AutoScroll = true;tableLayoutPanel1.RowCount = users.Count + 1;tableLayoutPanel1.ColumnCount = 1;tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.FixedSize;tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));foreach(用户中的字符串用户){tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 600F));}tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 600F));整数索引 = 0;foreach(用户中的字符串用户){AddDockedControl(索引,用户);索引++;}AddDockedControl(index, null);panel1.Controls.Add(tableLayoutPanel1);私人无效AddDockedControl(整数行,字符串用户名){AccountRowUC newUser = new AccountRowUC(this, userName, row);newUser.BorderStyle = BorderStyle.FixedSingle;newUser.Dock = DockStyle.Top;tableLayoutPanel1.Controls.Add(newUser, 0, row);}

现在,当我想删除其中一行时,我正在使用以下代码:

public void RemoveRowAtIndex(int index){if (index >= tableLayoutPanel1.RowCount)返回;//删除我们要删除的行的所有控件for (int i = 0; i < tableLayoutPanel1.ColumnCount; i++){var control = tableLayoutPanel1.GetControlFromPosition(i, index);tableLayoutPanel1.Controls.Remove(control);}//上移我们要删除的行之后的行控件for (int i = index + 1; i < tableLayoutPanel1.RowCount; i++){for (int j = 0; j < tableLayoutPanel1.ColumnCount; j++){var control = tableLayoutPanel1.GetControlFromPosition(j, i);如果(控制!= null)tableLayoutPanel1.SetRow(控件, i - 1);}}//删除最后一行tableLayoutPanel1.RowStyles.RemoveAt(tableLayoutPanel1.RowCount - 1);//tableLayoutPanel1.RowStyles.RemoveAt(index);tableLayoutPanel1.RowCount--;}
角色列表

问题是当我删除一个Row时,表格底部会留下一个很大的空间:TableLayoutPanel不会回收panel1的大小.

解决方案

基于评论中描述的布局和这个答案的解决方案,之前发布过:

由于通过测试而不是解释更容易理解它的工作原理,因此这里是表单的完整布局:

测试表格(frmTLPTest1):

使用 System.Drawing;使用 System.Linq;使用 System.Windows.Forms;公共部分类 frmTLPTest1 :表格{公共 frmTLPTest1(){初始化组件();tlp1.RowStyles.RemoveAt(1);}受保护的覆盖无效 OnLoad(EventArgs e){base.OnLoad(e);TlpAddRow(tlp1, false);}随机 rnd = new Random();尺寸[] 尺寸 = 新尺寸[] { 新尺寸(75, 75), 新尺寸(100, 100), 新尺寸(125, 125)};颜色 [] 颜色 = 新颜色 [] { Color.Red, Color.LightGreen, Color.YellowGreen, Color.SteelBlue };控件 selectedObject = null;控制 selectedParent = null;私人无效btnAddControl_Click(对象发送者,EventArgs e){尺寸 size = new Size(125, 125);if (chkRandom.Checked) size = sizes[rnd.Next(sizes.Length)];var pBox = new PictureBox() {Anchor = AnchorStyles.None,BackColor = 颜色[rnd.Next(colors.Length)],最小尺寸 = 尺寸,大小 = 大小};bool drawborder = false;pBox.MouseEnter += (s, evt) =>{drawborder =真;pBox.Invalidate();};pBox.MouseLeave += (s, evt) =>{ 画框 = 假;pBox.Invalidate();};pBox.MouseDown += (s, evt) =>{ selectedParent = pBox.Parent;选定对象 = pBox;pBox.Invalidate();};pBox.Paint += (s, evt) =>{如果(绘制边框){ControlPaint.DrawBorder(evt.Graphics, pBox.ClientRectangle,颜色.白色, ButtonBorderStyle.Solid);}};if (tlp1.RowCount == 0) TlpAddRow(tlp1, true);var ctl = tlp1.GetControlFromPosition(0, tlp1.RowCount - 1);int 整体With = 0;if (ctl.Controls?.Count > 0) {totalWith = ctl.Controls.OfType().Sum(c => c.Width + c.Margin.Left + c.Margin.Right);}整体与 += ctl.Margin.Right + ctl.Margin.Left + pBox.Size.Width + pBox.Margin.Left + pBox.Margin.Right;if (overallWith >= tlp1.Width) {ctl = TlpAddRow(tlp1, true);}ctl.Controls.Add(pBox);}私人无效btnRemoveRow_Click(对象发送者,EventArgs e){如果(selectedParent 为空)返回;if (selectedParent.Controls.Count > 0) {for (int i = 0; i == selectedParent.Controls.Count - 1; i++) {selectedParent.Controls[i].Dispose();}}TLPRemoveRow(tlp1, selectedParent);selectedParent.Dispose();}私人无效btnRemoveControl_Click(对象发送者,EventArgs e){如果(selectedObject 为空)返回;控件父 = selectedObject.Parent;selectedObject.Dispose();if (parent?.Controls.Count == 0) {TLPRemoveRow(tlp1, 父级);父母.Dispose();}}私有控件 TlpAddRow(TableLayoutPanel tlp, bool addRowCount){var flp = new FlowLayoutPanel() {锚点 = AnchorStyles.Top |AnchorStyles.Bottom,自动尺寸 = 真,AutoSizeMode = AutoSizeMode.GrowAndShrink,};tlp.SuspendLayout();if (addRowCount) tlp.RowCount += 1;tlp.Controls.Add(flp, 0, tlp.RowCount - 1);tlp.ResumeLayout(true);返回flp;}private void TLPRemoveRow(TableLayoutPanel tlp,控制控件){int ctlRow = tlp.GetRow(控制);TLPRemoveRow(tlp, ctlRow);}私有无效 TLPRemoveRow(TableLayoutPanel tlp,int 行){如果(行 < tlp.RowCount - 1){for (int i = row; i < tlp.RowCount - 1; i++) {tlp.SetRow(tlp.GetControlFromPosition(0, i + 1), i);}}tlp.RowCount -= 1;}}

测试表单设计器:

部分类 frmTLPTest1{私有 System.ComponentModel.IContainer 组件 = null;受保护的覆盖无效处置(布尔处置){if (disposing && (components != null)) {组件.Dispose();}base.Dispose(处置);}私人无效初始化组件(){this.panToolbar = new System.Windows.Forms.Panel();this.btnRemoveRow = new System.Windows.Forms.Button();this.chkRandom = new System.Windows.Forms.CheckBox();this.btnRemoveControl = new System.Windows.Forms.Button();this.btnAddControl = new System.Windows.Forms.Button();this.panBackground = new System.Windows.Forms.Panel();this.tlp1 = new System.Windows.Forms.TableLayoutPanel();this.panToolbar.SuspendLayout();this.panBackground.SuspendLayout();this.SuspendLayout();////平移工具栏//this.panToolbar.BackColor = System.Drawing.Color.DarkOliveGreen;this.panToolbar.Controls.Add(this.btnRemoveRow);this.panToolbar.Controls.Add(this.chkRandom);this.panToolbar.Controls.Add(this.btnRemoveControl);this.panToolbar.Controls.Add(this.btnAddControl);this.panToolbar.Dock = System.Windows.Forms.DockStyle.Bottom;this.panToolbar.Location = new System.Drawing.Point(0, 359);this.panToolbar.Name = "panToolbar";this.panToolbar.Size = new System.Drawing.Size(552, 55);this.panToolbar.TabIndex = 2;////btnRemoveRow//this.btnRemoveRow.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((字节)(32)))));this.btnRemoveRow.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnRemoveRow.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnRemoveRow.FlatStyle = System.Windows.Forms.FlatStyle.Flat;this.btnRemoveRow.ForeColor = System.Drawing.Color.White;this.btnRemoveRow.Location = new System.Drawing.Point(261, 11);this.btnRemoveRow.Name = "btnRemoveRow";this.btnRemoveRow.Size = new System.Drawing.Size(119, 34);this.btnRemoveRow.TabIndex = 4;this.btnRemoveRow.Text = "删除行";this.btnRemoveRow.UseVisualStyleBackColor = false;this.btnRemoveRow.Click += new System.EventHandler(this.btnRemoveRow_Click);////chk随机//this.chkRandom.AutoSize = true;this.chkRandom.ForeColor = System.Drawing.Color.White;this.chkRandom.Location = new System.Drawing.Point(446, 20);this.chkRandom.Name = "chkRandom";this.chkRandom.Size = new System.Drawing.Size(94, 19);this.chkRandom.TabIndex = 3;this.chkRandom.Text = 随机大小";this.chkRandom.UseVisualStyleBackColor = true;////btnRemoveControl//this.btnRemoveControl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((字节)(32)))));this.btnRemoveControl.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnRemoveControl.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnRemoveControl.FlatStyle = System.Windows.Forms.FlatStyle.Flat;this.btnRemoveControl.ForeColor = System.Drawing.Color.White;this.btnRemoveControl.Location = new System.Drawing.Point(136, 11);this.btnRemoveControl.Name = "btnRemoveControl";this.btnRemoveControl.Size = new System.Drawing.Size(119, 34);this.btnRemoveControl.TabIndex = 2;this.btnRemoveControl.Text = "删除控件";this.btnRemoveControl.UseVisualStyleBackColor = false;this.btnRemoveControl.Click += new System.EventHandler(this.btnRemoveControl_Click);////btnAddControl//this.btnAddControl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((字节)(32)))));this.btnAddControl.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnAddControl.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((字节)(0)))));this.btnAddControl.FlatStyle = System.Windows.Forms.FlatStyle.Flat;this.btnAddControl.ForeColor = System.Drawing.Color.White;this.btnAddControl.Location = new System.Drawing.Point(11, 11);this.btnAddControl.Name = "btnAddControl";this.btnAddControl.Size = new System.Drawing.Size(119, 34);this.btnAddControl.TabIndex = 0;this.btnAddControl.Text = "添加控件";this.btnAddControl.UseVisualStyleBackColor = false;this.btnAddControl.Click += new System.EventHandler(this.btnAddControl_Click);////平移背景//this.panBackground.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)|System.Windows.Forms.AnchorStyles.Left)|System.Windows.Forms.AnchorStyles.Right)));this.panBackground.AutoScroll = true;this.panBackground.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;this.panBackground.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((字节)(32)))));this.panBackground.Controls.Add(this.tlp1);this.panBackground.Location = new System.Drawing.Point(0, 0);this.panBackground.Name = "panBackground";this.panBackground.Size = new System.Drawing.Size(552, 360);this.panBackground.TabIndex = 3;////tlp1//this.tlp1.AutoSize = true;this.tlp1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;this.tlp1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((字节)(32)))));this.tlp1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;this.tlp1.ColumnCount = 1;this.tlp1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());this.tlp1.ColumnStyles.Add(新 System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));this.tlp1.Dock = System.Windows.Forms.DockStyle.Top;this.tlp1.Location = new System.Drawing.Point(0, 0);this.tlp1.Name = "tlp1";this.tlp1.RowCount = 1;this.tlp1.RowStyles.Add(new System.Windows.Forms.RowStyle());this.tlp1.RowStyles.Add(新 System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 1F));this.tlp1.Size = new System.Drawing.Size(552, 2);this.tlp1.TabIndex = 4;////frmTLPTest1//this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;this.ClientSize = new System.Drawing.Size(552, 414);this.Controls.Add(this.panBackground);this.Controls.Add(this.panToolbar);this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));this.Name = "frmTLPTest1";this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;this.Text = "frmTLPTest1";this.Load += new System.EventHandler(this.SOfrmTest1_Load);this.panToolbar.ResumeLayout(false);this.panToolbar.PerformLayout();this.panBackground.ResumeLayout(false);this.panBackground.PerformLayout();this.ResumeLayout(false);}私有 System.Windows.Forms.Panel panToolbar;私有 System.Windows.Forms.Button btnAddControl;私有 System.Windows.Forms.Button btnRemoveControl;私有 System.Windows.Forms.CheckBox chkRandom;私有 System.Windows.Forms.Panel panBackground;私有 System.Windows.Forms.TableLayoutPanel tlp1;私有 System.Windows.Forms.Button btnRemoveRow;}

I have a WinForms application that has a TableLayoutPanel; this is the definition code:

tableLayoutPanel1 = new TableLayoutPanel();
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.AutoScroll = true;

tableLayoutPanel1.RowCount = users.Count + 1;
tableLayoutPanel1.ColumnCount = 1;
tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.FixedSize;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));

foreach (String user in users)
{
    tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 600F));
}
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 600F));

int index = 0;
foreach (String user in users)
{
    AddDockedControl(index, user);
    index++;
}
AddDockedControl(index, null);

panel1.Controls.Add(tableLayoutPanel1);

private void AddDockedControl(int row, String userName)
{
    AccountRowUC newUser = new AccountRowUC(this, userName, row);
    newUser.BorderStyle = BorderStyle.FixedSingle;
    newUser.Dock = DockStyle.Top;
    tableLayoutPanel1.Controls.Add(newUser, 0, row);
}

Now, when I want to remove one of the rows, I'm using this code:

public void RemoveRowAtIndex(int index)
{
    if (index >= tableLayoutPanel1.RowCount)
        return;

    // delete all controls of row that we want to delete
    for (int i = 0; i < tableLayoutPanel1.ColumnCount; i++)
    {
        var control = tableLayoutPanel1.GetControlFromPosition(i, index);
        tableLayoutPanel1.Controls.Remove(control);
    }

    // move up row controls that comes after row we want to remove
    for (int i = index + 1; i < tableLayoutPanel1.RowCount; i++)
    {
        for (int j = 0; j < tableLayoutPanel1.ColumnCount; j++)
        {
            var control = tableLayoutPanel1.GetControlFromPosition(j, i);
            if (control != null)
                tableLayoutPanel1.SetRow(control, i - 1);
        }
    }

    // remove last row

    tableLayoutPanel1.RowStyles.RemoveAt(tableLayoutPanel1.RowCount - 1);
    //tableLayoutPanel1.RowStyles.RemoveAt(index);
    tableLayoutPanel1.RowCount--;
}

The problem is that when I remove a Row, a big space is left at the bottom of the table: the TableLayoutPanel won't reclaim the size of panel1.

解决方案

A solution base on the layout described in the comments and this answer, previously posted: Center multiple rows of controls in a FlowLayoutPanel

Description: (Full code of a test Form provided at bottom of this post)

Create a new Form (here, named frmTLPTest1) Add two Panels. One is used to host some buttons, the other one will be the Container of a TableLayoutPanel. Set the Container panel to AutoScroll = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, set all the Anchors (Left, Top, Right, Bottom) Inside the Container panel, drop a new TableLayoutPanel: set it to AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, Dock = DockStyle.Top Remove all Rows and Columns from the TableLayoutPanel except one of each (you cannot remove all). Set the dimensions of both to AutoSize.

Important note (also reported in the linked answer):

In the Form constructor, one of the RowStyles is removed. This is important: the TLP will keep 2 RowStyles. One is applied to the existing Row; the second style will be applied to the first Row you add: to the first one only, not the others. If this style is not removed, it will compromise the layout.

The core methods used to Add Rows to/Remove Rows from the TableLayoutPanel, make use of a FlowLayoutPanel as the TLP Row content and can also be used as Container of other controls, eventually.

TlpAddRow(TableLayoutPanel tlp, bool addRowCount) method: Adds a new FlowLayoutPanel to the Cell of the TableLayoutPanel specified and adds a new Row if requested. Since the Designer won't allow to remove all the Rows, the First Row (FlowLayoutPanel) must not increment the Rows count: the addRowCount argument will be set to false.

private Control TlpAddRow(TableLayoutPanel tlp, bool addRowCount)
{
    var flp = new FlowLayoutPanel() {
        Anchor = AnchorStyles.Top | AnchorStyles.Bottom,
        AutoSize = true,
        AutoSizeMode = AutoSizeMode.GrowAndShrink,
    };

    tlp.SuspendLayout();
    if (addRowCount) tlp.RowCount += 1;
    tlp.Controls.Add(flp, 0, tlp.RowCount - 1);
    tlp.ResumeLayout(true);
    return flp;
}

TLPRemoveRow(TableLayoutPanel tlp, Control control) method (overloaded):

Allows to remove a Row from the specified TableLayoutPanel. The Row to be removed can be derived from the Control that is used as the Row Container (a FlowLayoutPanel, here, but it could be a Panel, another TableLayoutPanel, or some other type of Container control). The Row can also be removed by directly specifying the Row index.

private void TLPRemoveRow(TableLayoutPanel tlp, Control control)
{
    int ctlRow = tlp.GetRow(control);
    TLPRemoveRow(tlp, ctlRow);
}

private void TLPRemoveRow(TableLayoutPanel tlp, int row)
{
    if (row < tlp.RowCount - 1) {
        for (int i = row; i < tlp.RowCount - 1; i++) {
            tlp.SetRow(tlp.GetControlFromPosition(0, i + 1), i);
        }
    }
    tlp.RowCount -= 1;
}

Visual results of this Layout:

Since it's easier to understand how it work by testing rather than explaining, here's the full layout of the Form:

Test Form (frmTLPTest1):

using System.Drawing;
using System.Linq;
using System.Windows.Forms;

public partial class frmTLPTest1 : Form
{
    public frmTLPTest1()
    {
        InitializeComponent();
        tlp1.RowStyles.RemoveAt(1);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        TlpAddRow(tlp1, false);
    }

    Random rnd = new Random();
    Size[] sizes = new Size[] { new Size(75, 75), new Size(100, 100), new Size(125, 125)};
    Color[] colors = new Color[] { Color.Red, Color.LightGreen, Color.YellowGreen, Color.SteelBlue };
    Control selectedObject = null;
    Control selectedParent = null;

    private void btnAddControl_Click(object sender, EventArgs e)
    {
        Size size = new Size(125, 125);
        if (chkRandom.Checked) size = sizes[rnd.Next(sizes.Length)];
        
        var pBox = new PictureBox() {
            Anchor = AnchorStyles.None,
            BackColor = colors[rnd.Next(colors.Length)],
            MinimumSize = size,
            Size = size
        };

        bool drawborder = false;
        pBox.MouseEnter += (s, evt) => { drawborder = true;  pBox.Invalidate(); };
        pBox.MouseLeave += (s, evt) => { drawborder = false; pBox.Invalidate(); };
        pBox.MouseDown += (s, evt) => { selectedParent = pBox.Parent;
                                        selectedObject = pBox;  pBox.Invalidate();
        };
        pBox.Paint += (s, evt) => {
            if (drawborder) {
                ControlPaint.DrawBorder(evt.Graphics, pBox.ClientRectangle, 
                                        Color.White, ButtonBorderStyle.Solid);
            }
        };

        if (tlp1.RowCount == 0) TlpAddRow(tlp1, true); 

        var ctl = tlp1.GetControlFromPosition(0, tlp1.RowCount - 1);
        int overallWith = 0;
        if (ctl.Controls?.Count > 0) {
            overallWith = ctl.Controls.OfType<Control>().Sum(c => c.Width + c.Margin.Left + c.Margin.Right);
        }
        overallWith += ctl.Margin.Right + ctl.Margin.Left + pBox.Size.Width + pBox.Margin.Left + pBox.Margin.Right;

        if (overallWith >= tlp1.Width) {
            ctl = TlpAddRow(tlp1, true);
        }
        ctl.Controls.Add(pBox);
    }

    private void btnRemoveRow_Click(object sender, EventArgs e)
    {
        if (selectedParent is null) return;
        if (selectedParent.Controls.Count > 0) {
            for (int i = 0; i == selectedParent.Controls.Count - 1; i++) {
                selectedParent.Controls[i].Dispose();
            }
        }
        TLPRemoveRow(tlp1, selectedParent);
        selectedParent.Dispose();
    }

    private void btnRemoveControl_Click(object sender, EventArgs e)
    {
        if (selectedObject is null) return;
        Control parent = selectedObject.Parent;
        selectedObject.Dispose();

        if (parent?.Controls.Count == 0) {
            TLPRemoveRow(tlp1, parent);
            parent.Dispose();
        }
    }

    private Control TlpAddRow(TableLayoutPanel tlp, bool addRowCount)
    {
        var flp = new FlowLayoutPanel() {
            Anchor = AnchorStyles.Top | AnchorStyles.Bottom,
            AutoSize = true,
            AutoSizeMode = AutoSizeMode.GrowAndShrink,
        };

        tlp.SuspendLayout();
        if (addRowCount) tlp.RowCount += 1;
        tlp.Controls.Add(flp, 0, tlp.RowCount - 1);
        tlp.ResumeLayout(true);
        return flp;
    }

    private void TLPRemoveRow(TableLayoutPanel tlp, Control control)
    {
        int ctlRow = tlp.GetRow(control);
        TLPRemoveRow(tlp, ctlRow);
    }

    private void TLPRemoveRow(TableLayoutPanel tlp, int row)
    {
        if (row < tlp.RowCount - 1) {
            for (int i = row; i < tlp.RowCount - 1; i++) {
                tlp.SetRow(tlp.GetControlFromPosition(0, i + 1), i);
            }
        }
        tlp.RowCount -= 1;
    }
}

Test Form Designer:

partial class frmTLPTest1
{
    private System.ComponentModel.IContainer components = null;
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null)) {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.panToolbar = new System.Windows.Forms.Panel();
        this.btnRemoveRow = new System.Windows.Forms.Button();
        this.chkRandom = new System.Windows.Forms.CheckBox();
        this.btnRemoveControl = new System.Windows.Forms.Button();
        this.btnAddControl = new System.Windows.Forms.Button();
        this.panBackground = new System.Windows.Forms.Panel();
        this.tlp1 = new System.Windows.Forms.TableLayoutPanel();
        this.panToolbar.SuspendLayout();
        this.panBackground.SuspendLayout();
        this.SuspendLayout();
        // 
        // panToolbar
        // 
        this.panToolbar.BackColor = System.Drawing.Color.DarkOliveGreen;
        this.panToolbar.Controls.Add(this.btnRemoveRow);
        this.panToolbar.Controls.Add(this.chkRandom);
        this.panToolbar.Controls.Add(this.btnRemoveControl);
        this.panToolbar.Controls.Add(this.btnAddControl);
        this.panToolbar.Dock = System.Windows.Forms.DockStyle.Bottom;
        this.panToolbar.Location = new System.Drawing.Point(0, 359);
        this.panToolbar.Name = "panToolbar";
        this.panToolbar.Size = new System.Drawing.Size(552, 55);
        this.panToolbar.TabIndex = 2;
        // 
        // btnRemoveRow
        // 
        this.btnRemoveRow.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
        this.btnRemoveRow.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnRemoveRow.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnRemoveRow.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.btnRemoveRow.ForeColor = System.Drawing.Color.White;
        this.btnRemoveRow.Location = new System.Drawing.Point(261, 11);
        this.btnRemoveRow.Name = "btnRemoveRow";
        this.btnRemoveRow.Size = new System.Drawing.Size(119, 34);
        this.btnRemoveRow.TabIndex = 4;
        this.btnRemoveRow.Text = "Remove Row";
        this.btnRemoveRow.UseVisualStyleBackColor = false;
        this.btnRemoveRow.Click += new System.EventHandler(this.btnRemoveRow_Click);
        // 
        // chkRandom
        // 
        this.chkRandom.AutoSize = true;
        this.chkRandom.ForeColor = System.Drawing.Color.White;
        this.chkRandom.Location = new System.Drawing.Point(446, 20);
        this.chkRandom.Name = "chkRandom";
        this.chkRandom.Size = new System.Drawing.Size(94, 19);
        this.chkRandom.TabIndex = 3;
        this.chkRandom.Text = "Random Size";
        this.chkRandom.UseVisualStyleBackColor = true;
        // 
        // btnRemoveControl
        // 
        this.btnRemoveControl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
        this.btnRemoveControl.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnRemoveControl.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnRemoveControl.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.btnRemoveControl.ForeColor = System.Drawing.Color.White;
        this.btnRemoveControl.Location = new System.Drawing.Point(136, 11);
        this.btnRemoveControl.Name = "btnRemoveControl";
        this.btnRemoveControl.Size = new System.Drawing.Size(119, 34);
        this.btnRemoveControl.TabIndex = 2;
        this.btnRemoveControl.Text = "Remove Control";
        this.btnRemoveControl.UseVisualStyleBackColor = false;
        this.btnRemoveControl.Click += new System.EventHandler(this.btnRemoveControl_Click);
        // 
        // btnAddControl
        // 
        this.btnAddControl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
        this.btnAddControl.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnAddControl.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
        this.btnAddControl.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.btnAddControl.ForeColor = System.Drawing.Color.White;
        this.btnAddControl.Location = new System.Drawing.Point(11, 11);
        this.btnAddControl.Name = "btnAddControl";
        this.btnAddControl.Size = new System.Drawing.Size(119, 34);
        this.btnAddControl.TabIndex = 0;
        this.btnAddControl.Text = "Add Control";
        this.btnAddControl.UseVisualStyleBackColor = false;
        this.btnAddControl.Click += new System.EventHandler(this.btnAddControl_Click);
        // 
        // panBackground
        // 
        this.panBackground.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
        | System.Windows.Forms.AnchorStyles.Left) 
        | System.Windows.Forms.AnchorStyles.Right)));
        this.panBackground.AutoScroll = true;
        this.panBackground.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        this.panBackground.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
        this.panBackground.Controls.Add(this.tlp1);
        this.panBackground.Location = new System.Drawing.Point(0, 0);
        this.panBackground.Name = "panBackground";
        this.panBackground.Size = new System.Drawing.Size(552, 360);
        this.panBackground.TabIndex = 3;
        // 
        // tlp1
        // 
        this.tlp1.AutoSize = true;
        this.tlp1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        this.tlp1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
        this.tlp1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
        this.tlp1.ColumnCount = 1;
        this.tlp1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
        this.tlp1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
        this.tlp1.Dock = System.Windows.Forms.DockStyle.Top;
        this.tlp1.Location = new System.Drawing.Point(0, 0);
        this.tlp1.Name = "tlp1";
        this.tlp1.RowCount = 1;
        this.tlp1.RowStyles.Add(new System.Windows.Forms.RowStyle());
        this.tlp1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 1F));
        this.tlp1.Size = new System.Drawing.Size(552, 2);
        this.tlp1.TabIndex = 4;
        // 
        // frmTLPTest1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.ClientSize = new System.Drawing.Size(552, 414);
        this.Controls.Add(this.panBackground);
        this.Controls.Add(this.panToolbar);
        this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.Name = "frmTLPTest1";
        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        this.Text = "frmTLPTest1";
        this.Load += new System.EventHandler(this.SOfrmTest1_Load);
        this.panToolbar.ResumeLayout(false);
        this.panToolbar.PerformLayout();
        this.panBackground.ResumeLayout(false);
        this.panBackground.PerformLayout();
        this.ResumeLayout(false);
    }

    private System.Windows.Forms.Panel panToolbar;
    private System.Windows.Forms.Button btnAddControl;
    private System.Windows.Forms.Button btnRemoveControl;
    private System.Windows.Forms.CheckBox chkRandom;
    private System.Windows.Forms.Panel panBackground;
    private System.Windows.Forms.TableLayoutPanel tlp1;
    private System.Windows.Forms.Button btnRemoveRow;
}

 
精彩推荐
图片推荐