He estado luchando con esto por un tiempo, y descubrí que otras personas también luchan con TableLayoutPanel (.net 2.0 Winforms).
Problema
Estoy intentando tomar un panel de diseño de tabla 'en blanco', que tiene 10 columnas definidas, luego, en tiempo de ejecución, agrego filas de controles mediante programación (es decir, un control por celda).
Se 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. Entonces tal vez agregando un estilo de fila
myTableLayoutPanel.RowStyles.Clear();
myTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
Pero eso tampoco funciona. Investigué y descubrí que el myTableLayoutPanel.RowCount
uso cambia desde el tiempo de diseño hasta el tiempo de ejecución, por lo tanto, hacerlo myTableLayoutPanel.RowCount++;
no agrega otra fila, ¡ni siquiera antes / después de agregar una entrada RowStyle!
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 de TableLayoutPanel, además, ni siquiera están restringidos a estar dentro de los límites de la celda que se supone que deben estar mostrados dentro (es decir, con Dock = DockStyle.Fill todavía parecen demasiado grandes / pequeños)
¿Alguien tiene un ejemplo práctico de agregar filas y controles en tiempo de ejecución?
Respuestas:
Hice esto la semana pasada. Ajuste el
GrowStyle
en laTableLayoutPanel
queAddRows
oAddColumns
, 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++; }
los
TableLayoutPanel
siempre me ajusta a la talla. En mi ejemplo anterior, estoy presentando una tarjeta de dirección que podría crecer o reducirse dependiendo de que la cuenta 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 estirará, coloco la etiqueta vacía allí para forzar una nueva fila vacía, luego todo se alinea bien.Aquí está el código del diseñador para que pueda ver la tabla con la que comienzo:
// // 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;
fuente
Es un diseño extraño, pero la
TableLayoutPanel.RowCount
propiedad no refleja el recuento de laRowStyles
colección, y lo mismo ocurre con laColumnCount
propiedad y laColumnStyles
colección.Lo que encontré que necesitaba en mi código era actualizar manualmente
RowCount
/ColumnCount
después de realizar cambios enRowStyles
/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 que un control llene una celda en la Grid; He hecho esto estableciendo laAnchors
propiedad del control.Si está agregando muchos controles, asegúrese de llamar
SuspendLayout
yResumeLayout
rodear el proceso; de lo contrario, las cosas se ejecutarán lentamente, ya que todo el formulario se volverá a publicar después de agregar cada control.fuente
Aquí está mi código para agregar 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; }
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 son generalmente de tipo Label y tienen su propiedad AutoSize establecida en true.
No creo que importe demasiado, pero como referencia, aquí está el código del 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 controles, le sugiero que elimine todo el TableLayoutPanel y cree uno nuevo.
fuente
Cree un panel de diseño de tabla con dos columnas en su formulario y asígnele un 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, ejecute el código.
fuente
Solo miré en mi código. En una aplicación, solo agrego los controles, pero sin especificar el índice, y cuando termino, simplemente recorro los estilos de fila y establezco el tipo de tamaño en AutoSize. Entonces, simplemente agregarlos sin especificar los índices parece agregar las filas según lo previsto (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 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 distribución de la mesa.
fuente
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
fuente
Esto funciona perfectamente para agregar filas y controles en un TableLayoutPanel.
Defina un panel de diseño de tabla 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
fuente
Acabo de tener un problema relacionado (que es cómo encontré este hilo), donde mis estilos de fila y columna agregados dinámicamente no estaban surtiendo efecto. Por lo general, considero SuspendLayout () / ResumeLayout () como optimizaciones, pero en este caso, envolver mi código en ellas hizo que las filas y columnas se comportaran correctamente.
fuente