简体   繁体   English

Winforms TableLayoutPanel以编程方式添加行

[英]Winforms TableLayoutPanel adding rows programmatically

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 (ie 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.RowCount usage changes from design time to run time, hence doing myTableLayoutPanel.RowCount++; 我挖了一下,发现myTableLayoutPanel.RowCount用法从设计时间变为运行时间,因此做了myTableLayoutPanel.RowCount++; doesn't actually add another row, not even before/after adding a RowStyle entry for it! 实际上并没有添加另一行,甚至在添加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 (ie with Dock = DockStyle.Fill they still appear way too large/small). 我遇到的另一个相关问题是控件将被添加到显示器,但它们都只是在TableLayoutPanel的点0,0处渲染,另外它们甚至不被限制在它们应该是的Cell边界内。显示在内(即使用Dock = DockStyle.Fill它们仍然显得太大/太小)。

Does someone have a working example of adding rows & controls at runtime? 有人有一个在运行时添加行和控件的工作示例吗?

I just did this last week. 我上周才这样做了。 Set the GrowStyle on the TableLayoutPanel to AddRows or AddColumns , then your code should work: TableLayoutPanel上的GrowStyle设置为AddRowsAddColumns ,然后您的代码应该工作:

// 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 TableLayoutPanel always gives me fits with size. TableLayoutPanel总是让我适合大小。 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. 在上面的示例中,我提交的地址卡可能会增长或缩小,具体取决于具有地址行2或国家/地区的帐户。 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. 因为表格布局面板的最后一行或列会拉伸,我会在那里抛出空标签以强制换出一个新的空行,然后一切排好。

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;

It's a weird design, but the TableLayoutPanel.RowCount property doesn't reflect the count of the RowStyles collection, and similarly for the ColumnCount property and the ColumnStyles collection. 这是一个奇怪的设计,但TableLayoutPanel.RowCount属性不反映RowStyles集合的计数,类似于ColumnCount属性和ColumnStyles集合。

What I've found I needed in my code was to manually update RowCount / ColumnCount after 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.Fill to make a control fill a cell in the Grid; 我从来没有使用DockStyle.Fill来控制填充网格中的单元格; I've done this by setting the Anchors property of the control. 我通过设置控件的Anchors属性来完成此操作。

  • If you're adding a lot of controls, make sure you call SuspendLayout and ResumeLayout around the process, else things will run slow as the entire form is relaid after each control is added. 如果你要添加很多控件,请确保在整个过程中调用SuspendLayoutResumeLayout ,否则在添加每个控件后整个表单都会重新启动时,事情会变慢。

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). 您应该知道,使用Controls属性(至少在某些版本的框架中)动态地从TableLayoutPanel处理控件时似乎存在一些问题。 If you need to remove controls, I suggest disposing the entire TableLayoutPanel and creating a new one. 如果你需要删除控件,我建议处理整个TableLayoutPanel并创建一个新的。

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. 最后,运行代码。

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. 在一个应用程序中,我只是添加控件,但没有指定索引,完成后,我只是遍历行样式并将大小类型设置为AutoSize。 So just adding them without specifying the indices seems to add the rows as intended (provided the GrowStyle is set to AddRows). 所以只是添加它们而不指定索引似乎按预期添加行(假设GrowStyle设置为AddRows)。

In another application, I clear the controls and set the RowCount property to the needed value. 在另一个应用程序中,我清除控件并将RowCount属性设置为所需的值。 This does not add the RowStyles. 这不会添加RowStyles。 Then I add my controls, this time specifying the indices, and add a new RowStyle ( RowStyles.Add(new RowStyle(...) ) and this also works. 然后我添加我的控件,这次指定索引,并添加一个新的RowStyle( RowStyles.Add(new RowStyle(...) ),这也有效。

So, pick one of these methods, they both work. 所以,选择其中一种方法,它们都有效。 I remember the headaches the table layout panel caused me. 我记得表布局面板给我带来的麻烦。

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

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()视为优化,但在这种情况下,将代码包装在其中使得行和列的行为正确。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM