Winforms TableLayoutPanel以编程方式添加行


85

我已经为此进行了一段时间的战斗,并且发现许多其他人也为TableLayoutPanel(.net 2.0 Winforms)感到困扰。

问题

我正在尝试采用“空白” tablelayoutpanel,其中定义了10列,然后在运行时以编程方式添加控件行(即,每个单元格一个控件)。

可能有人认为它应该像

myTableLayoutPanel.Controls.Add(myControl, 0 /* Column Index */, 0 /* Row index */);

但这(对我而言)不会添加行。所以也许添加一行样式

myTableLayoutPanel.RowStyles.Clear();
myTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));

但这也不起作用。我进行了挖掘,发现myTableLayoutPanel.RowCount用法从设计时间到运行时间都发生了变化,因此myTableLayoutPanel.RowCount++;实际上并没有添加另一行,甚至没有为它添加RowStyle条目之前/之后!

我遇到的另一个相关问题是控件将被添加到显示中,但是它们都只是在TableLayoutPanel的点0,0处呈现,此外,它们甚至不被限制在它们应该被视为的Cell范围内显示在其中(即Dock = DockStyle.Fill,它们仍然显得太大/太小)。

有人在运行时添加行和控件的工作示例吗?


添加RowStyle实际上会增加RowStyles.Count()
爱德华多·埃尔南德斯

Answers:


75

我上周刚做过。设置GrowStyleTableLayoutPanelAddRowsAddColumns,那么你的代码应工作:

// Adds "myControl" to the first column of each row
myTableLayoutPanel.Controls.Add(myControl1, 0 /* Column Index */, 0 /* Row index */);
myTableLayoutPanel.Controls.Add(myControl2, 0 /* Column Index */, 1 /* Row index */);
myTableLayoutPanel.Controls.Add(myControl3, 0 /* Column Index */, 2 /* Row index */);

这是一些似乎与您正在执行的工作代码类似的代码:

    private Int32 tlpRowCount = 0;

    private void BindAddress()
    {
        Addlabel(Addresses.Street);
        if (!String.IsNullOrEmpty(Addresses.Street2))
        {
            Addlabel(Addresses.Street2);
        }
        Addlabel(Addresses.CityStateZip);
        if (!String.IsNullOrEmpty(Account.Country))
        {
            Addlabel(Address.Country);
        }
        Addlabel(String.Empty); // Notice the empty label...
    }

    private void Addlabel(String text)
    {            
        label = new Label();
        label.Dock = DockStyle.Fill;
        label.Text = text;
        label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        tlpAddress.Controls.Add(label, 1, tlpRowCount);
        tlpRowCount++;
    }

TableLayoutPanel总是给我用一刀切。在上面的示例中,我要提交的地址卡可能会增加或缩小,具体取决于拥有第二行地址的帐户或国家/地区。因为表格布局面板的最后一行或最后一列会拉伸,所以我在其中放置了空标签以强制添加新的空行,然后所有内容都很好地对齐了。

这是设计器代码,因此您可以看到我开始的表格:

        //
        // tlpAddress
        // 
        this.tlpAddress.AutoSize = true;
        this.tlpAddress.BackColor = System.Drawing.Color.Transparent;
        this.tlpAddress.ColumnCount = 2;
        this.tlpAddress.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F));
        this.tlpAddress.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
        this.tlpAddress.Controls.Add(this.pictureBox1, 0, 0);
        this.tlpAddress.Dock = System.Windows.Forms.DockStyle.Fill;
        this.tlpAddress.Location = new System.Drawing.Point(0, 0);
        this.tlpAddress.Name = "tlpAddress";
        this.tlpAddress.Padding = new System.Windows.Forms.Padding(3);
        this.tlpAddress.RowCount = 2;
        this.tlpAddress.RowStyles.Add(new System.Windows.Forms.RowStyle());
        this.tlpAddress.RowStyles.Add(new System.Windows.Forms.RowStyle());
        this.tlpAddress.Size = new System.Drawing.Size(220, 95);
        this.tlpAddress.TabIndex = 0;

2
完美,简单的例子。
RandomInsano 2010年

2
感谢您提出一个空的占位符行的想法!解决了我的尺码问题。
JNadal

30

这是一个奇怪的设计,但是TableLayoutPanel.RowCount属性无法反映RowStyles集合的数量,对于ColumnCount属性和ColumnStyles集合也是如此。

我发现我需要在代码中进行的更改是在RowCount/ColumnCount之后手动更新RowStyles/ ColumnStyles

这是我使用的代码示例:

    /// <summary>
    /// Add a new row to our grid.
    /// </summary>
    /// The row should autosize to match whatever is placed within.
    /// <returns>Index of new row.</returns>
    public int AddAutoSizeRow()
    {
        Panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        Panel.RowCount = Panel.RowStyles.Count;
        mCurrentRow = Panel.RowCount - 1;
        return mCurrentRow;
    }

其他想法

  • 我从未用过DockStyle.Fill让控件填充Grid中的单元格的方法。我通过设置Anchors控件的属性来完成此操作。

  • 如果你加入了大量的控件,请确保调用SuspendLayoutResumeLayout周围的过程,否则事情会缓慢运行的添加的每个控制后,整个形式重新铺设。


2
如果对任何人有用,就我而言,我必须调用tableLayoutPanel1.ColumnStyles.Clear();。表单加载时。
约翰

17

这是将新行添加到两列TableLayoutColumn的代码:

private void AddRow(Control label, Control value)
{
    int rowIndex = AddTableRow();
    detailTable.Controls.Add(label, LabelColumnIndex, rowIndex);
    if (value != null)
    {
        detailTable.Controls.Add(value, ValueColumnIndex, rowIndex);
    }
}

private int AddTableRow()
{
    int index = detailTable.RowCount++;
    RowStyle style = new RowStyle(SizeType.AutoSize);
    detailTable.RowStyles.Add(style);
    return index;
}

标签控件位于左列,而值控件位于右列。控件通常为Label类型,其AutoSize属性设置为true。

我认为这没什么大不了的,但是作为参考,下面是设置detailTable的设计器代码:

this.detailTable.ColumnCount = 2;
this.detailTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.detailTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.detailTable.Dock = System.Windows.Forms.DockStyle.Fill;
this.detailTable.Location = new System.Drawing.Point(0, 0);
this.detailTable.Name = "detailTable";
this.detailTable.RowCount = 1;
this.detailTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.detailTable.Size = new System.Drawing.Size(266, 436);
this.detailTable.TabIndex = 0;

这一切都很好。您应该意识到,使用Controls属性动态地从TableLayoutPanel布置控件似乎存在一些问题(至少在某些框架版本中)。如果您需要删除控件,建议您放置整个TableLayoutPanel并创建一个新的。


这非常有帮助。我发现DockStyle.Fill属性是必不可少的。此外,计数很容易出错!另外,请注意用样式设置的列和行大小。我发现,当RowStyle设置为AutoSize时,TextAlign设置中的一些意外变化(在Top,Middle和Bottom中)使该表似乎以某种奇怪的方式生成了额外的行,但事实并非如此。一旦弄清楚,事情就很好了,但是到达那里真是痛苦!
Jan Hettich

7

创建一个具有两个列的表格布局面板,并将其命名tlpFields

然后,只需将新控件添加到表布局面板中(在本例中,我在第1列中添加了5个标签,在第2列中添加了5个文本框)。

tlpFields.RowStyles.Clear();  //first you must clear rowStyles

for (int ii = 0; ii < 5; ii++)
{
    Label l1= new Label();
    TextBox t1 = new TextBox();

    l1.Text = "field : ";

    tlpFields.Controls.Add(l1, 0, ii);  // add label in column0
    tlpFields.Controls.Add(t1, 1, ii);  // add textbox in column1

    tlpFields.RowStyles.Add(new RowStyle(SizeType.Absolute,30)); // 30 is the rows space
}

最后,运行代码。


您如何访问tlpfields?我创建了tablelayoutpanel,它的名称是tabkelayout,但是我无法访问它。
Muneem Habib

@MuneemHabib转到tabkelayout属性,并将修改器从私有更改为公共
RookieCoder

4

我只是查看了我的代码。在一个应用程序中,我只添加了控件,但未指定索引,完成后,我仅遍历行样式并将大小类型设置为AutoSize。因此,仅添加它们而不指定索引似乎可以按预期添加行(假设GrowStyle设置为AddRows)。

在另一个应用程序中,我清除控件并将RowCount属性设置为所需的值。这不会添加RowStyles。然后添加控件,这次指定索引,并添加新的RowStyle(RowStyles.Add(new RowStyle(...)),这也有效。

因此,选择这些方法之一,它们都可以工作。我记得桌子布局面板让我头疼。


我将试着看看它们是否表现良好!
Ash Ash

0
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim dt As New DataTable
        Dim dc As DataColumn
        dc = New DataColumn("Question", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("Ans1", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans2", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans3", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans4", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("AnsType", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)


        Dim Dr As DataRow
        Dr = dt.NewRow
        Dr("Question") = "What is Your Name"
        Dr("Ans1") = "Ravi"
        Dr("Ans2") = "Mohan"
        Dr("Ans3") = "Sohan"
        Dr("Ans4") = "Gopal"
        Dr("AnsType") = "Multi"
        dt.Rows.Add(Dr)

        Dr = dt.NewRow
        Dr("Question") = "What is your father Name"
        Dr("Ans1") = "Ravi22"
        Dr("Ans2") = "Mohan2"
        Dr("Ans3") = "Sohan2"
        Dr("Ans4") = "Gopal2"
        Dr("AnsType") = "Multi"
        dt.Rows.Add(Dr)
        Panel1.GrowStyle = TableLayoutPanelGrowStyle.AddRows
        Panel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
        Panel1.BackColor = Color.Azure
        Panel1.RowStyles.Insert(0, New RowStyle(SizeType.Absolute, 50))
        Dim i As Integer = 0

        For Each dri As DataRow In dt.Rows



            Dim lab As New Label()
            lab.Text = dri("Question")
            lab.AutoSize = True

            Panel1.Controls.Add(lab, 0, i)


            Dim Ans1 As CheckBox
            Ans1 = New CheckBox()
            Ans1.Text = dri("Ans1")
            Panel1.Controls.Add(Ans1, 1, i)

            Dim Ans2 As RadioButton
            Ans2 = New RadioButton()
            Ans2.Text = dri("Ans2")
            Panel1.Controls.Add(Ans2, 2, i)
            i = i + 1

            'Panel1.Controls.Add(Pan)
        Next

问题是关于TableLayoutPanel的,这篇文章是关于DataTable的。该帖子仅用于代码。它没有任何文字说明可能的含义。代码中也没有注释。因此,-1。
尼克·阿列克谢耶夫

0

这非常适合在TableLayoutPanel中添加行和控件。

在设计页面中定义一个包含3列的空白Tablelayoutpanel

    Dim TableLayoutPanel3 As New TableLayoutPanel()

    TableLayoutPanel3.Name = "TableLayoutPanel3"

    TableLayoutPanel3.Location = New System.Drawing.Point(32, 287)

    TableLayoutPanel3.AutoSize = True

    TableLayoutPanel3.Size = New System.Drawing.Size(620, 20)

    TableLayoutPanel3.ColumnCount = 3

    TableLayoutPanel3.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single

    TableLayoutPanel3.BackColor = System.Drawing.Color.Transparent

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 26.34146!))

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 73.65854!))

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 85.0!))

    Controls.Add(TableLayoutPanel3)

创建一个按钮btnAddRow以在每次单击时添加行

     Private Sub btnAddRow_Click(sender As System.Object, e As System.EventArgs) Handles btnAddRow.Click

          TableLayoutPanel3.GrowStyle = TableLayoutPanelGrowStyle.AddRows

          TableLayoutPanel3.RowStyles.Add(New RowStyle(SizeType.Absolute, 20))

          TableLayoutPanel3.SuspendLayout()

          TableLayoutPanel3.RowCount += 1

          Dim tb1 As New TextBox()

          Dim tb2 As New TextBox()

          Dim tb3 As New TextBox()

          TableLayoutPanel3.Controls.Add(tb1 , 0, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.Controls.Add(tb2, 1, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.Controls.Add(tb3, 2, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.ResumeLayout()

          tb1.Focus()

 End Sub

0

我只是遇到了一个相关的问题(这是我找到此线程的方式),其中我动态添加的行和列样式未生效。我通常将SuspendLayout()/ ResumeLayout()视为优化,但是在这种情况下,将代码包装在其中可以使行和列的行为正确。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.