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

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); 
} 

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

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--; 
} 

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

请您参考如下方法:

基于评论和此答案中描述的布局的解决方案,以前发布:
Center multiple rows of controls in a FlowLayoutPanel

描述:
(本文底部提供了测试表单的完整代码)

  1. 创建一个新表单(此处命名为frmTLPTest1)
  2. 添加两个面板。一个用于承载一些按钮,另一个将是 TableLayoutPanel 的容器。
  3. 将 Container 面板设置为 AutoScroll = trueAutoSizeMode = AutoSizeMode.GrowAndShrink,设置所有 anchor (Left、Top、Right、Bottom)
  4. 在容器面板中,放置一个新的 TableLayoutPanel:将其设置为 AutoSize = trueAutoSizeMode = AutoSizeMode.GrowAndShrinkDock = DockStyle.Top
  5. 从 TableLayoutPanel 中删除所有行和列,但每行和列除外(不能全部删除)。将两者的尺寸设置为 AutoSize

重要说明(也在链接的答案中报告):

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.

用于向 TableLayoutPanel 添加行/从中删除行的核心方法使用 FlowLayoutPanel 作为 TLP 行内容,最终也可以用作其他控件的容器。

TlpAddRow(TableLayoutPanel tlp, bool addRowCount)方法:
将新的 FlowLayoutPanel 添加到指定的 TableLayoutPanel 的单元格中,并在需要时添加新的行。
由于设计器不允许删除所有行,因此第一 (FlowLayoutPanel) 不得增加行数:addRowCount 参数将设置为 假的

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) 方法(重载):

允许从指定的 TableLayoutPanel 中删除一行。要删除的行可以派生自用作行容器的控件(此处为 FlowLayoutPanel,但它可以是面板、另一个 TableLayoutPanel 或其他类型的容器控件)。
也可以通过直接指定Row索引来移除Row。

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; 
} 

此布局的视觉结果:

由于通过测试比解释更容易理解它是如何工作的,下面是表单的完整布局:

测试表(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; 
    } 
} 

测试表单设计器:

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; 
} 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!