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
Winforms TableLayoutPanel adding rows programmatically
提问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.RowCount
usage 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 GrowStyle
on the TableLayoutPanel
to AddRows
or AddColumns
, then your code should work:
我上周刚做了这个。设置GrowStyle
上TableLayoutPanel
以AddRows
或AddColumns
,那么你的代码应工作:
// 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. 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.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 cellin the Grid; I've done this by setting theAnchors
property of the control.If you're adding a lot of controls, make sure you call
SuspendLayout
andResumeLayout
around the process, else things will run slow as the entire form is relaid after each control is added.
我从来没有
DockStyle.Fill
让控件填充网格中的单元格;我通过设置Anchors
控件的属性来做到这一点。如果您要添加大量控件,请确保调用
SuspendLayout
和ResumeLayout
围绕该过程,否则由于在添加每个控件后重新放置整个表单,所以运行速度会很慢。
回答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() 视为优化,但在这种情况下,将我的代码包装在其中会使行和列的行为正确。