Winforms TableLayoutPanel добавляет строки программно
Я некоторое время борется с этим, и обнаружил, что многие другие люди также борются с 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!
Еще одна связанная с этим проблема связана с тем, что элементы управления будут добавлены на дисплей, но все они просто будут отображаться в точке 0,0 таблицы TableLayoutPanel, кроме того, они даже не ограничены, чтобы быть в пределах ячеек, которые они которые должны отображаться внутри (то есть с Dock = DockStyle.Fill они все еще выглядят слишком большими/маленькими).
Есть ли у кого-нибудь рабочий пример добавления строк и элементов управления во время выполнения?
Ответы
Ответ 1
Я только что сделал это на прошлой неделе. Установите 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 */);
Вот какой рабочий код выглядит похоже на то, что вы делаете:
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
Это странный дизайн, но свойство 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
элемента управления.
-
Если вы добавляете множество элементов управления, убедитесь, что вы вызываете SuspendLayout
и ResumeLayout
вокруг процесса, иначе все будет работать медленно, так как вся форма будет передана после добавления каждого элемента управления.
Ответ 3
Здесь мой код для добавления новой строки в столбец TableLayoutCallumn с двумя столбцами:
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;
Все это работает отлично. Вы должны знать, что, как представляется, возникают проблемы с удалением элементов управления из TableLayoutPanel динамически с использованием свойства Controls (по крайней мере, в некоторых версиях фреймворка). Если вам нужно удалить элементы управления, я предлагаю удалить всю таблицу TableLayoutPanel и создать новую.
Ответ 4
Создайте панель макета таблицы с двумя столбцами в форме и назовите ее tlpFields
.
Затем просто добавьте новый элемент управления в панель макета таблицы (в этом случае я добавил 5 меток в столбцах 1 и 5 текстовых полей в столбце-2).
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
}
Наконец, запустите код.
Ответ 5
Я просто просмотрел свой код. В одном приложении я просто добавляю элементы управления, но не указывая индекс, и когда это делается, я просто просматриваю стили строк и устанавливаю тип размера в AutoSize. Таким образом, просто добавление их без указания индексов, кажется, добавляет строки по назначению (если для параметра GrowStyle установлено значение AddRows).
В другом приложении я очищаю элементы управления и устанавливаю свойство RowCount в необходимое значение. Это не добавляет RowStyles. Затем я добавляю свои элементы управления, на этот раз задавая индексы, и добавляю новый RowStyle (RowStyles.Add(new RowStyle(...)
), и это также работает.
Итак, выберите один из этих методов, они оба работают. Я помню головные боли, вызванные таблицей макета таблицы.
Ответ 6
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
Ответ 7
Это отлично работает для добавления строк и элементов управления в TableLayoutPanel.
Определите пустую панель Tablelayout с тремя столбцами на странице дизайна
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
Ответ 8
У меня была связанная с этим проблема (так я нашел этот поток), где мои динамически добавленные стили строк и столбцов не вступили в силу. Обычно я рассматриваю SuspendLayout()/ResumeLayout() как оптимизацию, но в этом случае обертывание моего кода в них приводило к правильной работе строк и столбцов.