Pregunta Winforms TableLayoutPanel que agrega filas programáticamente


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 "sin formato" de tablelayout, 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 descubrí que myTableLayoutPanel.RowCount el uso cambia del tiempo de diseño al tiempo de ejecución, lo que hace 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?


76
2017-07-17 12:07


origen


Respuestas:


Acabo de hacer esto la semana pasada. Selecciona el GrowStyle sobre el TableLayoutPanel a AddRows o AddColumns, entonces tu 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 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;

70
2018-02-02 05:58



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

Lo que encontré que necesitaba en mi código era actualizarlo manualmente RowCount/ColumnCount después de hacer cambios en 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 llenar un celda en la rejilla; He hecho esto estableciendo el Anchors propiedad del control.

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


28
2018-02-21 21:52



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.


16
2018-02-18 16:02



Cree un panel de diseño de tabla con dos columnas en su formulario y asígnele el 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.


7
2017-10-02 08:52



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.


4
2017-07-17 12:18



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
2018-03-20 23:14



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

0
2017-09-30 08:30