81 votes

Winforms TableLayoutPanel ajoutant des lignes de manière programmatique

Je me bats avec ce problème depuis un certain temps, et j'ai constaté qu'un certain nombre d'autres personnes se débattent également avec le TableLayoutPanel (.net 2.0 Winforms).

Problème

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

On aurait pu penser que cela serait aussi simple que

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

Mais cela (pour moi) n'ajoute pas les rangées. Alors peut-être qu'en ajoutant un style de ligne

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

Mais ça ne marche pas non plus. J'ai creusé un peu et j'ai découvert que la fonction myTableLayoutPanel.RowCount L'utilisation change entre le moment de la conception et celui de l'exécution. myTableLayoutPanel.RowCount++; n'ajoute pas réellement une autre ligne, même pas avant/après avoir ajouté une entrée RowStyle pour celle-ci !

Un autre problème connexe que je rencontre est que les contrôles seront ajoutés à l'affichage, mais ils sont simplement rendus au point 0,0 du TableLayoutPanel, de plus ils ne sont même pas contraints d'être dans les limites de la cellule dans laquelle ils sont censés être affichés (c'est-à-dire avec Dock = DockStyle.Fill ils apparaissent toujours beaucoup trop grands/petits).

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

73voto

Billy Coover Points 1862

Je l'ai fait la semaine dernière. Réglez le GrowStyle sur le TableLayoutPanel a AddRows o AddColumns alors votre code devrait 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 fonctionnel 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++;
    }

Le site TableLayoutPanel me donne toujours des problèmes de taille. Dans mon exemple ci-dessus, je classe une carte d'adresse qui pourrait s'agrandir ou se rétrécir selon que le compte a une ligne d'adresse deux, ou un pays. Comme la dernière ligne, ou colonne, du panneau de mise en page du tableau s'étire, je place l'étiquette vide pour forcer une nouvelle ligne vide, et tout s'aligne parfaitement.

Voici le code du designer pour que vous puissiez voir le tableau avec lequel 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;

29voto

Bevan Points 20976

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

Ce dont j'ai eu besoin dans mon code était de mettre à jour manuellement RowCount / ColumnCount après avoir apporté des modifications à 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;
    }

Autres réflexions

  • Je n'ai jamais utilisé DockStyle.Fill pour qu'un contrôle remplisse un cellule dans la grille ; pour ce faire, j'ai défini la valeur de l'option Anchors du contrôle.

  • Si vous ajoutez beaucoup de contrôles, assurez-vous d'appeler SuspendLayout y ResumeLayout autour du processus, sinon les choses seront lentes, car le formulaire entier est rechargé après l'ajout de chaque contrôle.

17voto

Cory McCarty Points 410

Voici mon code pour ajouter une nouvelle ligne à une 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 de l'étiquette se trouve dans la colonne de gauche et le contrôle de la valeur dans la colonne de droite. Les contrôles sont généralement de type Label et leur propriété AutoSize est définie sur true.

Je ne pense pas que cela ait trop d'importance, 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 des contrôles d'un TableLayoutPanel de façon dynamique en utilisant la propriété Controls (au moins dans certaines versions du framework). Si vous devez supprimer des contrôles, je vous suggère de supprimer l'intégralité du TableLayoutPanel et d'en créer un nouveau.

7voto

Ali Motamedi Points 61

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

Ensuite, il suffit d'ajouter un nouveau contrôle au panneau de présentation 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, exécutez le code.

4voto

OregonGhost Points 16615

Je viens de regarder dans mon code. Dans une application, je me contente d'ajouter les contrôles, mais sans spécifier l'index, et lorsque j'ai terminé, je passe en revue les styles de ligne et je règle le type de taille sur AutoSize. Ainsi, le fait de les ajouter sans spécifier les indices semble ajouter les rangées comme prévu (à condition que le GrowStyle soit défini sur AddRows).

Dans une autre application, je vide les contrôles et je fixe la propriété RowCount à la valeur nécessaire. Cela n'ajoute pas les RowStyles. J'ajoute ensuite mes contrôles, en spécifiant cette fois les indices, et j'ajoute un nouveau RowStyle ( RowStyles.Add(new RowStyle(...) ) et cela fonctionne également.

Alors, choisissez l'une de ces méthodes, elles fonctionnent toutes les deux. Je me souviens des maux de tête que me causait le panneau de présentation des tableaux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X