it-swarm.com.de

Winforms TableLayoutPanel, das programmgesteuert Zeilen hinzufügt

Ich habe seit einiger Zeit damit zu kämpfen, und ich habe festgestellt, dass eine Reihe anderer Leute auch mit dem TableLayoutPanel (.net 2.0 Winforms) zu kämpfen haben.

Problem

Ich versuche, ein 'leeres' Tablelayoutpanel zu nehmen, das 10 definierte Spalten hat, und dann zur Laufzeit programmgesteuert Zeilen von Steuerelementen hinzufügen (d. H. Ein Steuerelement pro Zelle).

Man hätte gedacht, dass es so einfach sein sollte 

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

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

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

Das funktioniert aber auch nicht. Ich habe mich umgesehen und herausgefunden, dass sich die Verwendung von myTableLayoutPanel.RowCount von der Entwurfszeit zur Laufzeit ändert. Daher fügt myTableLayoutPanel.RowCount++; keine weitere Zeile hinzu, auch nicht vor/nach dem Hinzufügen eines RowStyle-Eintrags!

Ein anderes verwandtes Problem, dem ich begegne, ist, dass die Steuerelemente der Anzeige hinzugefügt werden. Sie werden jedoch alle einfach am Punkt 0,0 des TableLayoutPanels gerendert. Außerdem sind sie nicht einmal darauf beschränkt, innerhalb der Zellgrenzen zu sein, die sie sein sollen angezeigt innerhalb (dh mit Dock = DockStyle.Fill erscheinen sie immer noch viel zu groß/klein).

Hat jemand ein funktionierendes Beispiel für das Hinzufügen von Zeilen und Steuerelementen zur Laufzeit?

77
Ash

Ich habe das gerade letzte Woche gemacht. Setzen Sie GrowStyle für TableLayoutPanel auf AddRows oder AddColumns, dann sollte Ihr 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 funktionierender Code, 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++;
    }

Die TableLayoutPanel gibt mir immer die passende Größe. In meinem obigen Beispiel lege ich eine Adresskarte ab, die je nach Konto mit Adresszeile zwei oder Land wachsen oder schrumpfen kann. Da sich die letzte Zeile oder Spalte des Tabellenlayout-Bereichs überdehnt, werfe ich das leere Etikett hinein, um eine neue leere Zeile zu erzwingen.

Hier ist der Designer-Code, damit Sie die Tabelle sehen können, mit der ich beginne:

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

Es ist ein seltsames Design, aber die TableLayoutPanel.RowCount-Eigenschaft spiegelt nicht die Anzahl der RowStyles-Auflistung wider, ebenso die ColumnCount-Eigenschaft und die ColumnStyles-Auflistung.

Was ich in meinem Code gefunden habe, war das manuelle Aktualisieren von RowCount/ColumnCount, nachdem Änderungen an RowStyles/ColumnStyles vorgenommen wurden.

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 noch nie DockStyle.Fill verwendet, um ein Steuerelement auszufüllen, um ein cell im Grid zu füllen. Ich habe dies getan, indem Sie die Anchors-Eigenschaft des Steuerelements festgelegt haben.

  • Wenn Sie viele Steuerelemente hinzufügen, müssen Sie unbedingt SuspendLayout und ResumeLayout um den Prozess herum aufrufen. Andernfalls werden die Vorgänge langsam ausgeführt, da das gesamte Formular nach dem Hinzufügen jedes Steuerelements wiederhergestellt wird.

28
Bevan

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 befindet sich in der linken Spalte und das Value-Steuerelement in der rechten Spalte. Die Steuerelemente sind im Allgemeinen vom Typ Label und die AutoSize-Eigenschaft ist auf true festgelegt.

Ich glaube nicht, dass es zu wichtig ist, aber hier ist der Designer-Code, 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 dessen bewusst sein, dass es scheinbar Probleme gibt, Steuerelemente aus einem TableLayoutPanel mithilfe der Controls-Eigenschaft dynamisch zu entfernen (zumindest in einigen Versionen des Frameworks). Wenn Sie Steuerelemente entfernen müssen, empfehle ich, das gesamte TableLayoutPanel zu entsorgen und ein neues zu erstellen.

16
Cory McCarty

Erstellen Sie ein Tabellenlayoutfeld mit zwei Spalten in Ihrem Formular, und nennen Sie es tlpFields.

Fügen Sie dann einfach ein neues Steuerelement zum Tabellenlayoutfeld hinzu (in diesem Fall fügte ich 5 Beschriftungen in Spalte 1 und 5 Textfelder in Spalte 2 hinzu).

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 schließlich den Code aus.

7
Ali Motamedi

Ich habe nur in meinen Code geschaut. In einer Anwendung füge ich nur die Steuerelemente hinzu, aber ohne den Index anzugeben, und wenn ich fertig bin, schleife ich die Zeilenstile durch und setze den Größentyp auf AutoSize. Wenn Sie sie einfach hinzufügen, ohne die Indizes anzugeben, werden die Zeilen wie beabsichtigt 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 erforderlichen Wert. Dies fügt die RowStyles nicht hinzu. Dann füge ich meine Steuerelemente hinzu, diesmal mit Angabe der Indizes, und füge einen neuen RowStyle (RowStyles.Add(new RowStyle(...)) hinzu. Dies funktioniert auch.

Wählen Sie also eine dieser Methoden aus, die beide funktionieren. Ich erinnere mich an die Kopfschmerzen, die mir das Tabellenlayout-Panel verursachte.

4
OregonGhost

Ich hatte gerade ein verwandtes Problem (wie ich diesen Thread gefunden habe), bei dem meine dynamisch hinzugefügten Zeilen- und Spaltenstile nicht wirksam wurden. Normalerweise halte ich SuspendLayout ()/ResumeLayout () für Optimierungen, aber in diesem Fall haben die Zeilen und Spalten sich durch das Einschließen meines Codes korrekt verhalten.

0

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

Definieren Sie auf der Designseite ein leeres Tablelayout-Panel mit 3 Spalten

    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
EIV
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
Sujeet