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?
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;
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.
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.
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.
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.
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.
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
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