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