ejemplos c# .net winforms runtime tablelayoutpanel

c# - ejemplos - Winforms TableLayoutPanel que agrega filas programáticamente



table layout panel c# dynamic (8)

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).

Problema

Estoy intentando tomar un panel de panel de tareas ''en blanco'', que tiene 10 columnas definidas, luego, en tiempo de ejecución, programáticamente agregar filas de controles (es decir, un control por celda).

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

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

Pero eso (para mí) no agrega las filas. Así que tal vez agregar un estilo de fila

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

Pero eso tampoco funciona. He buscado y descubierto que el uso de myTableLayoutPanel.RowCount cambia del tiempo de diseño al tiempo de ejecución, por lo tanto, haciendo 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, adicionalmente ni siquiera están limitados a estar dentro de los límites de la Celda que se supone que son visualizados dentro (es decir, con Dock = DockStyle.Fill, siguen apareciendo demasiado grandes / pequeños).

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


Acabo de hacer esto la semana pasada. Establezca GrowStyle en TableLayoutPanel en AddRows o AddColumns , luego su 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 ajustes 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í está el código del diseñador para que pueda ver la tabla con la que empiezo:

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


Acabo de mirar 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 de tamaño en AutoSize. 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.

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


Acabo de tener un problema relacionado (que es cómo encontré este hilo), donde los estilos de columna y columna agregados dinámicamente 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.


Aquí está mi código para agregar una nueva fila a 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; }

El control de etiqueta va en la columna de la izquierda y el control de valor va en la columna de la 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ñador que configura 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 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.


Cree un panel de diseño de tabla con dos columnas en su formulario y tlpFields nombre 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, ejecuta el código.


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

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

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

/// <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 usado DockStyle.Fill para hacer un control de llenar una celda en la Grilla; Lo he hecho estableciendo la propiedad Anchors del control.

  • Si está agregando muchos controles, asegúrese de llamar a SuspendLayout y ResumeLayout todo el proceso, de lo contrario las cosas se ejecutarán lentamente ya que todo el formulario se relaizará después de agregar cada control.


Esto funciona perfectamente para agregar filas y controles en TableLayoutPanel.

Defina un panel de Tablelayout 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)

Cree un botón btnAddRow para agregar 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


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