2009-07-17 16 views
74

He estado luchando con esto por un tiempo, y he descubierto que otras personas también tienen problemas con el TableLayoutPanel (.NET 2.0 Winforms).Formas de pago TableLayoutPanel que agrega filas programáticamente

Problema

Estoy intentando tomar un TableLayoutPanel 'en blanco', que tiene 10 columnas definidas, a continuación, en tiempo de ejecución mediante programación añadir filas de los controles (es decir, uno de control por célula).

Uno podría haber pensado que debería ser tan simple como

myTableLayoutPanel.Controls.Add(myControl, 0 /* Column Index */, 0 /* Row index */); 

Pero que (para mí) no añade las filas. Entonces, quizás agregue un estilo de fila

myTableLayoutPanel.RowStyles.Clear(); 
myTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F)); 

Pero eso tampoco funciona. He buscado y descubrí que el uso de myTableLayoutPanel.RowCount cambia del tiempo de diseño al tiempo de ejecución, por lo tanto, hacer myTableLayoutPanel.RowCount++; en realidad no agrega otra fila, ni siquiera antes/después de agregar una entrada RowStyle para ella.

Otro problema relacionado que estoy encontrando es que los controles se agregarán a la pantalla, pero todos simplemente se renderizan en el punto 0,0 del TableLayoutPanel, ni siquiera están limitados a estar dentro de los límites de la celda que se supone que se muestran dentro (es decir, con Dock = DockStyle.Fill todavía aparecen demasiado grandes/pequeños).

¿Alguien tiene un ejemplo funcional de agregar filas & controles en tiempo de ejecución?

+0

Agregar un RowStyle en realidad aumentará el RowStyles.Count() –

Respuesta

4

Acabo de revisar mi código. En una aplicación, simplemente agregué los controles, pero sin especificar el índice, y cuando termine, simplemente recorro los estilos de fila y configuro el tamaño del tamaño en Tamaño automático. Entonces, simplemente agregarlos sin especificar los índices parece agregar las filas como se pretende (siempre que GrowStyle esté configurado en AddRows).

En otra aplicación, borro los controles y establezco la propiedad RowCount en el valor necesario. Esto no agrega los RowStyles. Luego agrego mis controles, esta vez especificando los índices, y agrego un nuevo RowStyle (RowStyles.Add(new RowStyle(...)) y esto también funciona.

Así que escoja uno de estos métodos, ambos funcionan. Recuerdo los dolores de cabeza que me causó el panel de diseño de la mesa.

+0

¡Voy a probar estos para ver si se comporta bien! – Ash

68

Acabo de hacer esto la semana pasada. Ajuste el GrowStyle en el TableLayoutPanel a AddRows o AddColumns, a continuación, el código debería funcionar:

// 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 */); 

Aquí hay un código de trabajo que parece similar a lo que está haciendo:

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++; 
    } 

El TableLayoutPanel siempre me da encaja con el tamaño. En mi ejemplo anterior, estoy archivando una tarjeta de dirección que puede crecer o reducirse según la cuenta que tenga una línea de dirección dos o un país. Debido a que la última fila, o columna, del panel de diseño de la tabla se alargará, tiro la etiqueta vacía para forzar una nueva fila vacía, y luego todo se alinea muy bien.

Aquí es el código del diseñador para que pueda ver la tabla comienzo con:

 // 
     // 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

Ejemplo perfecto y simple. – RandomInsano

+2

¡Gracias por la idea de una fila de marcador de posición vacía! Resolvió mis problemas de tamaño. – JNadal

16

Aquí está mi código para añadir una nueva fila a una TableLayoutColumn de dos columnas:

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; 
} 

La etiqueta el control va en la columna izquierda y el control de valor va en la columna derecha. Los controles generalmente son de tipo Label y tienen su propiedad AutoSize establecida en verdadero.

No creo que importe demasiado, pero para referencia, aquí está el código de diseño que establece 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; 

Todo esto funciona muy bien. Debe tener en cuenta que parece haber algunos problemas con la eliminación de controles de un TableLayoutPanel dinámicamente utilizando la propiedad Controls (al menos en algunas versiones del marco). Si necesita eliminar los controles, le sugiero que elimine todo el TableLayoutPanel y cree uno nuevo.

+0

Esto fue muy útil. Descubrí que el atributo DockStyle.Fill era esencial. ¡Además, es sorprendentemente fácil cometer errores con el conteo! Además, tenga en cuenta los tamaños de columna y fila establecidos con estilos. Descubrí que cuando RowStyle se configuraba en Tamaño automático, algunas variaciones involuntarias en la configuración de TextAlign (entre Arriba, Medio e Inferior) hacía que pareciera que la tabla generaba filas extra de alguna manera extraña, pero ese no era el caso. La cosa funciona bastante bien una vez que lo resuelves, ¡pero fue doloroso llegar allí! –

+0

Solución correcta –

28

Es un diseño extraño, pero la propiedad TableLayoutPanel.RowCount no refleja el conteo de la colección RowStyles, y lo mismo para la propiedad ColumnCount y la colección ColumnStyles.

Lo que he encontrado que necesitaba en mi código fue actualizar manualmente RowCount/ColumnCount después de hacer cambios a RowStyles/ColumnStyles.

Aquí hay un ejemplo de código que he utilizado:

/// <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; 
    } 

Otros pensamientos

  • nunca he utilizado DockStyle.Fill para hacer un control de llenar una celdaen la cuadrícula; Lo hice estableciendo la propiedad Anchors del control.

  • Si va a añadir una gran cantidad de controles, asegúrate de que llamar SuspendLayout y ResumeLayout todo el proceso, las demás cosas se ejecutará lento, ya que todo el formulario se relaid después de añadir cada control.

+2

Si es útil para cualquier persona, en mi caso tuve que llamar a * tableLayoutPanel1.ColumnStyles.Clear(); * cuando se está cargando el formulario. – 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

La pregunta es sobre TableLayoutPanel, esta publicación es sobre DataTable. La publicación es solo de código. No tiene ningún texto que describa cuál podría ser el punto. No hay comentarios en el código tampoco. Entonces, -1. –

7

Crear un panel de diseño tabla con dos columnas en su forma y nombre que tlpFields.

Luego, simplemente agregue un nuevo control al panel de diseño de la tabla (en este caso agregué 5 etiquetas en la columna-1 y 5 cuadros de texto en la columna-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 
} 

Finalmente, ejecute el código.

+0

cómo está accediendo a tlpfields? He creado tablelayoutpanel y su nombre es tabkelayout pero no estoy en condiciones de acceder a esto. –

+0

@MuneemHabib ve a las propiedades de tabkelayout y cambia ** Modificadores ** de privado a público – RookieCoder

0

Esto funciona perfectamente para agregar filas y controles en un TableLayoutPanel.

Definir un TableLayoutPanel en blanco con 3 columnas en la página de diseño

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) 

Crear un botón btnAddRow añadir filas en cada clic

 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

solo tuve un problema relacionado (que es como yo Encontré este hilo), donde mis estilos dinámicamente agregados de fila y columna no estaban teniendo efecto. Normalmente considero a SuspendLayout()/ResumeLayout() como optimizaciones, pero en este caso, al ajustar mi código en ellas, las filas y columnas se comportan correctamente.

Cuestiones relacionadas