Search code examples
.netwinformslabelpanelgroupbox

Controls in panel are hidden until I resize the window


I've been having issues with controls being "cut-off" from a panel. However when i manually start resizing the form, the missing controls start to re-appear after every resize. I've created a test app to show this issue. The app itself adds a panel on the main form. Within this panel i add 10 groupboxes with each groupbox having 100 labels. Below are the steps to create the test app and reproduce the issue (I've only tried this with .NET 4.6.1 and visual studio 2017 so far)

  • Create a new windows forms project
  • Update the constructor of the default form to be as below

    public Form1()
    {
        InitializeComponent();
    
        // My stuff
        var panContents = new Panel();
        panContents.AutoScroll = true;
        panContents.AutoSize = true;
        panContents.AutoSizeMode = AutoSizeMode.GrowAndShrink;
        panContents.Dock = DockStyle.Fill;
        for (int g = 10; g >= 0; g--)
        {
            var groupBox = new GroupBox();
            groupBox.AutoSize = true;
            groupBox.AutoSizeMode = AutoSizeMode.GrowOnly;
            groupBox.Dock = DockStyle.Top;
            groupBox.Text = "Group " + g;
    
            var mainPanel = new Panel();
            mainPanel.Dock = DockStyle.Fill;
            mainPanel.AutoSize = true;
            mainPanel.AutoSizeMode = AutoSizeMode.GrowOnly;
            for (int i = 100; i >= 0; i--)
            {
                var con = new Label();
                con.Text = "Label " + i;
                con.Height = 100;
                con.Dock = DockStyle.Top;
                mainPanel.Controls.Add(con);
            }
            groupBox.Controls.Add(mainPanel);
            panContents.Controls.Add(groupBox);
        }
    
        this.Controls.Add(panContents);
    }
    
  • Run the project (without resizing the form)

  • Scroll to near the bottom of the form, you'll notice not all the 10 group boxes are rendered
  • Manually resize the form, you'll notice some of the missing labels and groupboxes start to appear
  • Keep resizing the form until all the controls are shown

Anyone have any idea why this is happening? I thought maybe it was to do with the limit of the size of the panel. However if this was the case, i wouldn't expect resizing the form to start showing these missing controls.

PS I know i can get around this issue by using tabs or paging. However I want to know why I'm seeing the behaviour that I'm seeing (Ideally i want to avoid using tabs or paging)


Solution

  • @Yas,

    This was a rather intriguing problem--didn't quite grasp it until loading/running your code. I happen to agree with Jimi--that you're probably running up against an internal limitation, however bizarre that limitation appears to be. As you pointed out, tweaking the height/width of the form shouldn't overcome a limitation. So whatever's going on internally, it's a bit odd and unexpected.

    But I have a solution for you: It's admittedly a kludge but sometimes that's our only option. If your project specs require a form like the one you presented--a form that ends up with a height value well over 100,000, then this solution should fit the bill.

    Add the following code to the end of your Form1 initialization code, shown in your original post (see below). What I've done is programmatically "tweaked" the height of the form ever so slightly--repeatedly--until all of the panels have been fully rendered. I think this is going to be your best bet.

    For the record, I had spent quite a bit of time on this. I had tried various combinations of Refresh() on various controls, DoEvents(), etc., to no avail. I even tried not using docking and autosizing, in favor of setting top and heights manually (that didn't work either). Thus, I think the code below is really the only way to fix this, aside from a fix from Microsoft.

    ** For the code below to work, add this line immediately after your code's InitializeComponent(); line:

    this.Show();
    

    Then add this code after your code's closing brace:

         // fix the panContents panel
         long currentMaximum = 0;
         while (true)
         {
            var preserveHeight = this.Height;
            // tweak the height
            this.Height += 1;
            // set it back the height
            this.Height = preserveHeight;
    
            // test to see if the scroll bar max remains at its previous value
            // if it does, we're done
            if (currentMaximum == panContents.VerticalScroll.Maximum)
               break;
    
            // otherwise, preserve the current maximum scroll bar position
            currentMaximum = panContents.VerticalScroll.Maximum;
    
            // now scroll to the bottom of the panel
            panContents.VerticalScroll.Value = panContents.VerticalScroll.Maximum;
            // necessary step to ensure scroll bar value is set
            panContents.PerformLayout();
         }
    
         // scroll to the top
         panContents.VerticalScroll.Value = 0;
         // necessary step to ensure scroll bar value is set
         panContents.PerformLayout();