为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
繁星点点滴滴 2022-10-23 13:31:17
我有一个 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--;}问题是当我删除一个 Row 时,表格底部会留下一个很大的空间:TableLayoutPanel 不会回收panel1.
查看完整描述

1 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

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

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

  1. 创建一个新表单(这里,命名为frmTLPTest1

  2. 添加两个面板。一个用于承载一些按钮,另一个将是 TableLayoutPanel 的容器。

  3. 将 Container 面板设置为AutoScroll = trueAutoSizeMode = AutoSizeMode.GrowAndShrink, 设置所有 Anchors (Left, Top, Right, Bottom)

  4. 在 Container 面板中,放置一个新的 TableLayoutPanel:将其设置为AutoSize = trueAutoSizeMode = AutoSizeMode.GrowAndShrink,Dock = DockStyle.Top

  5. 从 TableLayoutPanel 中删除所有行和列,除了每个行和列(不能全部删除)。将两者的尺寸设置为AutoSize

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

在 Form 构造函数中,删除了其中一个 RowStyles。这很重要:TLP 将保留 2 个 RowStyle。一个应用于现有的 Row;第二种样式将应用于您添加的第一行:仅应用于第一个,而不应用于其他。如果不删除此样式,则会影响布局。

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

TlpAddRow(TableLayoutPanel tlp, bool addRowCount)方法:
将新的 FlowLayoutPanel 添加到指定的 TableLayoutPanel 的 Cell 中,并在请求时添加新的 Row。
由于设计器不允许删除所有行,因此第一(FlowLayoutPanel) 不得增加行数:addRowCount参数将设置为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)方法(重载):


允许从指定的 TableLayoutPanel 中删除行。要删除的 Row 可以从用作 Row Container 的 Control 派生(此处为 FlowLayoutPanel,但它可以是 Panel、另一个 TableLayoutPanel 或其他一些类型的 Container 控件)。

也可以通过直接指定 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;

}

此布局的视觉结果:

https://i.stack.imgur.com/hJs0i.gif

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


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

}



查看完整回答
反对 回复 2022-10-23
  • 1 回答
  • 0 关注
  • 98 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信