2009-07-17 2 views
74

Я некоторое время сражался с этим, и обнаружил, что многие другие люди также борются с TableLayoutPanel (.net 2.0 Winforms).Winforms TableLayoutPanel добавляет строки программным способом

Проблема

Я пытается принять «пустой» 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 они все еще выглядят слишком большими/маленькими).

У кого-нибудь есть рабочий пример добавления строк & элементов управления во время выполнения?

+0

Добавление RowStyle на самом деле увеличит значение RowStyles.Count() –

ответ

4

Я только что просмотрел свой код. В одном приложении я просто добавляю элементы управления, но не указывая индекс, и когда это делается, я просто просматриваю стили строк и устанавливаю тип размера в AutoSize. Таким образом, просто добавление их без указания индексов, кажется, добавляет строки по назначению (если для GrowStyle установлено значение AddRows).

В другом приложении я очищаю элементы управления и устанавливаю свойство RowCount в необходимое значение. Это не добавляет RowStyles. Затем я добавляю свои элементы управления, на этот раз определяя индексы, и добавляю новый RowStyle (RowStyles.Add(new RowStyle(...)), и это также работает.

Итак, выберите один из этих методов, они оба работают. Я помню головные боли, вызванные таблицей.

+0

. Я дам им попробовать посмотреть, ведет ли он себя! – Ash

68

Я только что сделал это на прошлой неделе. Установите 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

Идеальный, простой пример. – RandomInsano

+2

Благодарим за идею создания пустой строки-заполнителя! Решила мои вопросы по размеру. – JNadal

16

Вот мой код для добавления новой строки в две колонки 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 и создать новую.

+0

Это было очень полезно. Я обнаружил, что атрибут DockStyle.Fill необходим. Кроме того, удивительно легко ошибиться при подсчете! Также обратите внимание на размеры столбцов и строк, заданные со стилями. Я обнаружил, что когда RowStyle был настроен на AutoSize, некоторые непреднамеренные изменения в настройках TextAlign (среди Top, Middle и Bottom) показали, что таблица создавала лишние строки каким-то странным образом, но это было не так. Эта вещь работает очень хорошо, как только вы это понимаете, но было больно попасть туда! –

+0

Правильное решение –

28

Это странный дизайн, но 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 вокруг процесса, иначе все будет работать медленно, как вся форма relaid после добавления каждого элемента управления.

+2

Если это полезно для всех, в моем случае мне пришлось вызывать * tableLayoutPanel1.ColumnStyles.Clear(); * при загрузке формы. – John

0
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 
+0

Вопрос о TableLayoutPanel, этот пост о DataTable. Сообщение имеет только код. В нем нет текста, описывающего, что может быть. В коде нет комментариев. Таким образом, 1. –

7

Создание панели макета таблицы с двумя столбцами в вашей форме и назовите его 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 
} 

Наконец, запустите код.

+0

как вы обращаетесь к tlpfields? Я создал tablelayoutpanel, и его имя - tabkelayout, но я не имею доступа к этому. –

+0

@MuneemHabib перейти к свойствам и изменениям tabkelayout ** Модификаторы ** от частного до публичного – RookieCoder

0

Это прекрасно работает для добавления строк и элементов управления в TableLayoutPanel.

Определение заготовки TableLayoutPanel с 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 
0

Я просто имел родственную задачу (которая, как я нашел эту ветку), где мои динамически добавленные стили строк и столбцов не вступили в силу. Обычно я рассматриваю SuspendLayout()/ResumeLayout() как оптимизацию, но в этом случае, обертывая мой код, они корректно ведут строки и столбцы.

Смежные вопросы