Frage Winforms TableLayoutPanel fügt Zeilen programmgesteuert hinzu


Ich kämpfe seit einiger Zeit damit und habe festgestellt, dass auch andere Leute mit TableLayoutPanel (.net 2.0 WinForms) zu kämpfen haben.

Problem

Ich versuche, ein 'leeres' tabletayoutpanel zu nehmen, das 10 Spalten definiert hat, und füge dann zur Laufzeit programmgesteuert Zeilen von Steuerelementen hinzu (d. H. Ein Steuerelement pro Zelle).

Man könnte meinen, dass es so einfach sein sollte wie

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

Aber das (für mich) fügt die Zeilen nicht hinzu. Also vielleicht in einer Reihe Stil hinzufügen

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

Aber das funktioniert auch nicht. Ich habe gegraben und herausgefunden, dass die myTableLayoutPanel.RowCount Die Verwendung ändert sich von Entwurfszeit zu Laufzeit und damit auch myTableLayoutPanel.RowCount++; Fügt tatsächlich keine weitere Zeile hinzu, nicht einmal vor / nach dem Hinzufügen eines RowStyle-Eintrags dafür!

Ein anderes verwandtes Problem, das mir begegnet, ist, dass die Steuerelemente zur Anzeige hinzugefügt werden, aber alle werden einfach an Punkt 0,0 des TableLayoutPanel gerendert, außerdem sind sie nicht einmal darauf beschränkt, innerhalb der Zellgrenzen zu liegen, die sie sein sollen angezeigt (dh mit Dock = DockStyle.Fill erscheinen sie immer noch viel zu groß / klein).

Hat jemand ein funktionierendes Beispiel zum Hinzufügen von Zeilen und Steuerelementen zur Laufzeit?


76
2017-07-17 12:07


Ursprung


Antworten:


Das habe ich letzte Woche gemacht. Stellen Sie das ein GrowStyle auf der TableLayoutPanel zu AddRows oder AddColumns, dann sollte dein Code funktionieren:

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

Hier ist ein Arbeitscode, der dem ähnelt, was Sie tun:

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

Das TableLayoutPanel gibt mir immer passt mit der Größe. In meinem obigen Beispiel füge ich eine Adresskarte ein, die je nach dem Konto mit einer Adresszeile zwei oder einem Land wachsen oder schrumpfen kann. Da sich die letzte Zeile oder Spalte des Tabellenlayoutbedienfelds ausdehnt, werfe ich das leere Etikett dorthin, um eine neue leere Zeile zu erzwingen, dann wird alles gut ausgerichtet.

Hier ist der Designercode, damit Sie die Tabelle sehen können, mit der ich anfange:

        //
        // 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 ist ein komisches Design, aber die TableLayoutPanel.RowCount Eigenschaft spiegelt nicht die Anzahl der RowStyles Sammlung, und ähnlich für die ColumnCount Eigentum und die ColumnStyles Sammlung.

Was ich in meinem Code gefunden habe, war die manuelle Aktualisierung RowCount/ColumnCount nach Änderungen an RowStyles/ColumnStyles.

Hier ist ein Beispiel für Code, den ich verwendet habe:

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

Andere Gedanken

  • Ich habe nie benutzt DockStyle.Fill um eine Kontrolle zu füllen a Zelle im Gitter; Ich habe dies getan, indem ich die Anchors Eigenschaft der Kontrolle.

  • Wenn Sie viele Steuerelemente hinzufügen, sollten Sie unbedingt anrufen SuspendLayout und ResumeLayout Um den Prozess herum werden die Dinge sonst langsam ausgeführt, da das gesamte Formular nach dem Hinzufügen jedes Steuerelements neu hinzugefügt wird.


28
2018-02-21 21:52



Hier ist mein Code zum Hinzufügen einer neuen Zeile zu einer zweispaltigen 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;
}

Das Label-Steuerelement wird in der linken Spalte und das Wert-Steuerelement in der rechten Spalte angezeigt. Die Steuerelemente sind im Allgemeinen vom Typ Label und ihre AutoSize-Eigenschaft ist auf True festgelegt.

Ich denke nicht, dass es zu wichtig ist, aber als Referenz ist hier der Designercode, der detailTable einrichtet:

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;

Das alles funktioniert gut. Sie sollten sich darüber im Klaren sein, dass es Probleme gibt, Steuerelemente aus einem TableLayoutPanel mithilfe der Controls-Eigenschaft dynamisch zu verteilen (zumindest in einigen Versionen des Frameworks). Wenn Sie die Steuerelemente entfernen müssen, empfehle ich, das gesamte TableLayoutPanel zu entfernen und ein neues zu erstellen.


16
2018-02-18 16:02



Erstellen Sie ein Tabellenlayoutpanel mit zwei Spalten in Ihrem Formular und benennen Sie es tlpFields.

Dann fügen Sie dem Tabellenlayout-Panel einfach ein neues Steuerelement hinzu (in diesem Fall habe ich 5 Beschriftungen in Spalte-1 und 5-Textfelder in Spalte-2 hinzugefügt).

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
}

Führen Sie den Code schließlich aus.


7
2017-10-02 08:52



Ich habe gerade in meinen Code geschaut. In einer Anwendung füge ich einfach die Steuerelemente hinzu, aber ohne den Index anzugeben, und wenn das erledigt ist, durchlaufe ich einfach die Zeilenstile und setze den Größentyp auf AutoSize. Wenn Sie also nur die Indizes hinzufügen, ohne die Indizes anzugeben, werden die Zeilen wie vorgesehen hinzugefügt (vorausgesetzt, der GrowStyle ist auf AddRows gesetzt).

In einer anderen Anwendung lösche ich die Steuerelemente und setze die RowCount-Eigenschaft auf den benötigten Wert. Dies fügt die RowStyles nicht hinzu. Dann füge ich meine Steuerelemente hinzu, wobei ich diesmal die Indizes festlege, und füge einen neuen RowStyle hinzu (RowStyles.Add(new RowStyle(...)) und das funktioniert auch.

Also, wählen Sie eine dieser Methoden, sie funktionieren beide. Ich erinnere mich an die Kopfschmerzen, die mir das Table-Layout-Panel verursacht hat.


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



Dies funktioniert perfekt zum Hinzufügen von Zeilen und Steuerelementen in einem TableLayoutPanel.

Definieren Sie ein leeres Tabellayoutpanel mit 3 Spalten auf der Designseite

    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)

Erstellen Sie eine Schaltfläche btnAddRow, um bei jedem Klick Zeilen hinzuzufügen

     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