When is Panel.Size updated after adding controls when Panel.AutoSize = true?

Antoine Henry picture Antoine Henry · Jan 8, 2013 · Viewed 10.5k times · Source

I'm creating a GUI in C# using WinForms.
I'm trying to position programaticaly created panels one below the other. As the content of these panel can vary depending on their content, I'm using Panel.AutoSize to let WinForms perform the correct resizing.

The problem is: if I'm using Panel.Height (or Panel.Size.Height) right after populating the Panel, the value returned is always my default value. The resizing do occur, as I can see when launching the app, but I just don't know when.

Here's a simplified version of what I'm doing:

this.SuspendLayout();

int yPos = 0;
foreach (String entry in entries)
{
    Panel panel = new Panel();
    panel.SuspendLayout();
    panel.AutoSize = true;
    panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
    panel.BackColor = System.Drawing.SystemColors.Window; // Allows to see that the panel is resized for dispay
    panel.Location = new System.Drawing.Point(0, yPos);
    panel.Size = new System.Drawing.Size(this.Width, 0);
    this.Controls.Add(panel);

    Label label = new Label();
    label.AutoSize = true;
    label.Location = new System.Drawing.Point(0, 0);
    label.MaximumSize = new System.Drawing.Size(panel.Width, 0);
    label.Text = entry;
    panel.Controls.Add(label);

    panel.ResumeLayout(false);
    panel.PerformLayout();

    yPos += panel.Height; // When breaking here, panel.Height is worth 0
    yPos += label.Height; // This works perfectly, label.Height was updated according to the text content when breaking at that point
}

this.ResumeLayout(false);
this.PerformLayout();

So the real question is: How can I get the updated Panel.Size after adding controls to it, to get its proper height value?

Note: I know I can use the TextBox height, but I find it inelegant and impractical, as in my actual code there are more controls in the Panel and I need to use that panel height a few lines below.

Answer

Mark Hall picture Mark Hall · Jan 8, 2013

What I beleive is happening is that the Size of the Panel will be determined when you do PerformLayout on its Parent. You can make it work like you are wanting by moving the panel's parent SuspendLayout / ResumeLayout code into the Loop.

int yPos = 0;
foreach (String entry in entries)
{
    this.SuspendLayout();
    Panel panel = new Panel();
    panel.SuspendLayout();
    panel.AutoSize = true;
    panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
    panel.BackColor = System.Drawing.SystemColors.Window; // Allows to see that the panel is resized for dispay
    panel.Location = new System.Drawing.Point(0, yPos);
    panel.Size = new System.Drawing.Size(this.Width, 0);
    this.Controls.Add(panel);

    Label label = new Label();
    label.AutoSize = true;
    label.Location = new System.Drawing.Point(0, 0);
    label.MaximumSize = new System.Drawing.Size(panel.Width, 0);
    label.Text = entry;
    panel.Controls.Add(label);
    panel.ResumeLayout(true);
    this.ResumeLayout(true);
    yPos += panel.Height; // When breaking here, panel.Height is worth 0
    //yPos += label.Height; // This works perfectly, label.Height was updated according to the text content when breaking at that point
}
this.PerformLayout();