C# Winforms TableLayoutPanel 以编程方式添加行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1142873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 09:15:49  来源:igfitidea点击:

Winforms TableLayoutPanel adding rows programmatically

c#.netwinformsruntimetablelayoutpanel

提问by Ash

I've been fighting with this for a while, and have found that a number of other people struggle with the TableLayoutPanel (.net 2.0 Winforms) as well.

我已经为此奋斗了一段时间,并且发现许多其他人也在为 TableLayoutPanel(.net 2.0 Winforms)而苦恼。

Problem

问题

I am attempting to take a 'blank' tablelayoutpanel, which has 10 columns defined, then at runtime programmatically add rows of controls (i.e. one control per cell).

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

One might have thought that it should be as simple as

人们可能认为它应该像这样简单

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

But that (for me) doesn't add the rows. So maybe adding in a row style

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

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

But that doesn't work either. I've dug around and found out that the myTableLayoutPanel.RowCountusage changes from design time to run time, hence doing myTableLayoutPanel.RowCount++;doesn't actually add another row, not even before/after adding a RowStyle entry for it!

但这也行不通。我仔细研究了一下,发现myTableLayoutPanel.RowCount从设计时到运行时的用法都发生了变化,因此这样myTableLayoutPanel.RowCount++;做实际上并没有添加另一行,甚至在为它添加 RowStyle 条目之前/之后也没有!

Another related issue I am encountering is that the controls will be added to the display, but they all simply get rendered at point 0,0 of the TableLayoutPanel, additionally they are not even constrained to be within the Cell bounds that they are supposed to be displayed within (i.e. with Dock = DockStyle.Fill they still appear way too large/small).

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

Does someone have a working example of adding rows & controls at runtime?

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

回答by OregonGhost

I just looked into my code. In one application, I just add the controls, but without specifying the index, and when done, I just loop through the row styles and set the size type to AutoSize. So just adding them without specifying the indices seems to add the rows as intended (provided the GrowStyle is set to AddRows).

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

In another application, I clear the controls and set the RowCount property to the needed value. This does not add the RowStyles. Then I add my controls, this time specifying the indices, and add a new RowStyle (RowStyles.Add(new RowStyle(...)) and this also works.

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

So, pick one of these methods, they both work. I remember the headaches the table layout panel caused me.

因此,选择其中一种方法,它们都有效。我记得表格布局面板让我头疼。

回答by Billy Coover

I just did this last week. Set the GrowStyleon the TableLayoutPanelto AddRowsor AddColumns, then your code should work:

我上周刚做了这个。设置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 */);

Here is some working code that seems similar to what you are doing:

以下是一些与您正在执行的操作类似的工作代码:

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

The TableLayoutPanelalways gives me fits with size. In my example above, I'm filing an address card that might grow or shrink depending on the account having an address line two, or a country. Because the last row, or column, of the table layout panel will stretch, I throw the empty label in there to force a new empty row, then everything lines up nicely.

TableLayoutPanel总是给我用一刀切。在我上面的示例中,我提交的地址卡可能会根据具有第二行地址的帐户或国家/地区的不同而增加或缩小。因为表格布局面板的最后一行或一列会拉伸,所以我将空标签扔在那里以强制创建一个新的空行,然后一切都很好地排列起来。

Here is the designer code so you can see the table I start with:

这是设计器代码,所以你可以看到我开始的表格:

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

回答by Cory McCarty

Here's my code for adding a new row to a two-column TableLayoutColumn:

这是我向两列 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;
}

The label control goes in the left column and the value control goes in the right column. The controls are generally of type Label and have their AutoSize property set to true.

标签控件位于左列,值控件位于右列。这些控件通常是 Label 类型,并且它们的 AutoSize 属性设置为 true。

I don't think it matters too much, but for reference, here is the designer code that sets up detailTable:

我认为这并不重要,但作为参考,这里是设置 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;

This all works just fine. You should be aware that there appear to be some problems with disposing controls from a TableLayoutPanel dynamically using the Controls property (at least in some versions of the framework). If you need to remove controls, I suggest disposing the entire TableLayoutPanel and creating a new one.

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

回答by Bevan

It's a weird design, but the TableLayoutPanel.RowCountproperty doesn't reflect the count of the RowStylescollection, and similarly for the ColumnCountproperty and the ColumnStylescollection.

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

What I've found I needed in my code was to manually update RowCount/ColumnCountafter making changes to RowStyles/ColumnStyles.

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

Here's an example of code I've used:

这是我使用过的代码示例:

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

Other thoughts

其他想法

  • I've never used DockStyle.Fillto make a control fill a cellin the Grid; I've done this by setting the Anchorsproperty of the control.

  • If you're adding a lot of controls, make sure you call SuspendLayoutand ResumeLayoutaround the process, else things will run slow as the entire form is relaid after each control is added.

  • 我从来没有DockStyle.Fill让控件填充网格中的单元格;我通过设置Anchors控件的属性来做到这一点。

  • 如果您要添加大量控件,请确保调用SuspendLayoutResumeLayout围绕该过程,否则由于在添加每个控件后重新放置整个表单,所以运行速度会很慢。

回答by Sujeet

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

回答by Ali Motamedi

Create a table layout panel with two columns in your form and name it tlpFields.

在表单中创建一个包含两列的表格布局面板并将其命名为tlpFields

Then, simply add new control to table layout panel (in this case I added 5 labels in column-1 and 5 textboxes in column-2).

然后,只需将新控件添加到表格布局面板(在本例中,我在第 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
}

Finally, run the code.

最后,运行代码。

回答by EIV

This works perfectly for adding rows and controls in a TableLayoutPanel.

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

Define a blank Tablelayoutpanel with 3 columns in the design page

在设计页面中定义一个有 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)

Create a button btnAddRow to add rows on each click

创建一个按钮 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

回答by Wisdom's Beginning

I just had a related problem (which is how I found this thread), where my dynamically added row and column styles were not taking effect. I usually consider SuspendLayout()/ResumeLayout() as optimizations, but in this case, wrapping my code in them made the rows and columns behave correctly.

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