web-dev-qa-db-fra.com

Winforms TableLayoutPanel ajoutant des lignes par programme

Je me bats avec cela depuis un moment et j'ai constaté qu'un certain nombre d'autres personnes ont également des problèmes avec TableLayoutPanel (.net 2.0 Winforms).

Problème

J'essaie de prendre un tablelayoutpanel 'vide', qui a 10 colonnes définies, puis au moment de l'exécution d'ajouter par programme des rangées de contrôles (c'est-à-dire un contrôle par cellule).

On aurait pu penser que cela devrait être aussi simple que 

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

Mais cela (pour moi) n'ajoute pas les lignes. Alors peut-être ajouter dans un style de ligne

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

Mais ça ne marche pas non plus. J'ai fouillé et découvert que l'utilisation de myTableLayoutPanel.RowCount changeait d'une conception à l'autre, donc myTableLayoutPanel.RowCount++; n'ajoute pas une autre ligne, pas même avant/après l'ajout d'une entrée RowStyle!

Un autre problème connexe que je rencontre est que les contrôles seront ajoutés à l'affichage, mais ils seront tous simplement restitués au point 0,0 de TableLayoutPanel. affichés dans (c.-à-d. avec Dock = DockStyle.Fill, ils semblent encore trop grands/petits).

Quelqu'un a-t-il un exemple concret d'ajout de lignes et de contrôles au moment de l'exécution?

77
Ash

Je viens de faire cela la semaine dernière. Définissez GrowStyle sur TableLayoutPanel sur AddRows ou AddColumns, votre code devrait alors fonctionner:

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

Voici un code de travail qui semble similaire à ce que vous faites: 

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

La TableLayoutPanel me donne toujours la taille. Dans l'exemple ci-dessus, je dépose une carte d'adresse qui peut augmenter ou diminuer en fonction du compte ayant une ligne d'adresse deux ou un pays. Étant donné que la dernière ligne (ou colonne) du panneau de disposition du tableau va s'étirer, je jette l'étiquette vide à l'intérieur pour forcer une nouvelle ligne vide.

Voici le code du concepteur pour que vous puissiez voir la table par laquelle je commence:

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

C'est un design étrange, mais la propriété TableLayoutPanel.RowCount ne reflète pas le nombre de la collection RowStyles, et de la même manière pour la propriété ColumnCount et la collection ColumnStyles.

Ce que j'ai trouvé dans mon code, c'était de mettre à jour manuellement RowCount/ColumnCount après avoir modifié RowStyles/ColumnStyles.

Voici un exemple de code que j'ai utilisé:

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

D'autres pensées

  • Je n'ai jamais utilisé DockStyle.Fill pour qu'un contrôle remplisse un cellule dans la grille; Je l'ai fait en définissant la propriété Anchors du contrôle.

  • Si vous ajoutez beaucoup de contrôles, assurez-vous d'appeler SuspendLayout et ResumeLayout dans le processus, sinon tout se déroulera lentement car le formulaire complet sera relancé après l'ajout de chaque contrôle.

28
Bevan

Voici mon code pour ajouter une nouvelle ligne à un TableLayoutColumn à deux colonnes:

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

Le contrôle d'étiquette va dans la colonne de gauche et le contrôle de valeur dans la colonne de droite. Les contrôles sont généralement du type Label et leur propriété AutoSize est définie sur true.

Je ne pense pas que cela compte trop, mais pour référence, voici le code du concepteur qui configure 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;

Tout cela fonctionne très bien. Vous devez savoir qu'il semble y avoir quelques problèmes avec la suppression dynamique des contrôles d'un TableLayoutPanel à l'aide de la propriété Controls (au moins dans certaines versions du framework). Si vous devez supprimer des contrôles, je suggère de supprimer l'ensemble de TableLayoutPanel et d'en créer un nouveau.

16
Cory McCarty

Créez un panneau de présentation de tableau avec deux colonnes dans votre formulaire et nommez-le tlpFields.

Ensuite, ajoutez simplement un nouveau contrôle au panneau de disposition du tableau (dans ce cas, j'ai ajouté 5 étiquettes dans la colonne 1 et 5 zones de texte dans la colonne 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
}

Enfin, lancez le code.

7
Ali Motamedi

Je viens de regarder dans mon code. Dans une application, j'ajoute simplement les contrôles, mais sans spécifier l'index. Une fois terminé, je boucle sur les styles de lignes et je règle le type de taille sur AutoSize. Il suffit donc de les ajouter sans spécifier les index pour ajouter les lignes comme prévu (à condition que GrowStyle soit défini sur AddRows).

Dans une autre application, j'efface les contrôles et attribue à la propriété RowCount la valeur requise. Cela n'ajoute pas les RowStyles. Ensuite, j'ajoute mes contrôles, cette fois en spécifiant les index, et ajoute un nouveau RowStyle (RowStyles.Add(new RowStyle(...)), ce qui fonctionne également.

Alors, choisissez l'une de ces méthodes, elles fonctionnent toutes les deux. Je me souviens des maux de tête que le panneau de la table m'a causés.

4
OregonGhost

Je viens d'avoir un problème connexe (c'est comment j'ai trouvé ce fil), où mes styles de lignes et de colonnes ajoutés dynamiquement ne prenaient pas effet. Je considère généralement SuspendLayout ()/ResumeLayout () comme des optimisations, mais dans ce cas, en y insérant mon code, les lignes et les colonnes se comportaient correctement.

0
Wisdom's Beginning

Cela fonctionne parfaitement pour ajouter des lignes et des contrôles dans un TableLayoutPanel.

Définir un tableau vide avec 3 colonnes dans la page de conception

    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)

Créer un bouton btnAddRow pour ajouter des lignes à chaque 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
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