Error FlowLayoutPanel Height when using AutoSize

I have a form containing a TableLayout with 1 column and 3 rows, which contains 2 FlowLayoutPanels and a text box. All rows are AutoSize, and Percentage = 100% is set in the column.

Each FlowLayoutPanel contains several text fields. The flags of FlowLayoutPanels are set: LeftToRight, AutoSize = true, GrowAndShrink, Docking = Fill.

Circuit:

Form TableLayout (Dock=Fill) FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) More controls FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) More controls TextBox(Dock=Fill, MultiLine=true) 

The problem is that I put the FlowLayoutPanel inside the GroupBox, which is also set to AutoSize = true, the height of the FlowLayoutPanel is set incorrectly, and it shows TextBoxes in 1 line, cutting some TextBoxes from the form.

Circuit:

 Form TableLayout (Dock=Fill) GroupBox (Dock=Fill, AutoSize=True, GrowShrink) FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) More controls GroupBox (Dock=Fill, AutoSize=True, GrowShrink) FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) More controls TextBox(Dock=Fill, MultiLine=true) 

By the way, the same thing happens if I use instead of GroupBox, Panel or even UserControl to store the FlowLayoutPanel.

By the way 2, this happens even without a TableLayout. I tried to place a GroupBox (with FlowLayoutPanel) in an AutoSize Form, and I get the same behavior.

I think the problem is that when the FlowLayoutPanel is in another container, which is also AutoSize, it cannot pass the container to it, the preferred size.

What can be done to undo this error?

Please help Thanks, Yoram


ps: I have to use GroupBox to have a nice frame around text fields.

+5
source share
3 answers

Also ran into this problem and tried to figure out how to easily solve this problem. Although @GertArnold's answer helped, it felt a bit cumbersome and I was looking for another solution.

What I discovered was that the Flow Panel auto-parsing logic worked on the minimum requirements, and by adding an empty panel with a minimum height, I was able to force the control panel to widen, thereby making all other child controls visible.

therefore, in the example above, the final layout will look like this:

 Form TableLayout (Dock=Fill) GroupBox (Dock=Fill, AutoSize=True, GrowShrink) FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) Panel(Dock=Fill, Height = 1, MinimumSize = new System.Drawing.Size( Form.ClientSize.Width - TableLayout.Padding.Horizontal, 1)) More controls GroupBox (Dock=Fill, AutoSize=True, GrowShrink) FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink) Panel(Dock=Fill, Height = 1, MinimumSize = new System.Drawing.Size( Form.ClientSize.Width - TableLayout.Padding.Horizontal, 1)) More controls TextBox(Dock=Fill, MultiLine=true) 

Hope this helps.

+2
source

When you complete the FlowLayoutPanel in a GroupBox (or other containers), you can also leave them AutoSize=false . I'm not sure, but it can make groupbox a “leading” control when it comes to size.


Edit (after your comment)

"Lead control" - these are my words, trying to express that the size of a group package will determine the value of FLP, this is not some official term. The problem is that docking and automation are fighting each other in nature , and someone has to take, well, control. This can be done only if docking and auto-change are reduced, and programming the resizing events themselves.

After a little game, I finally came up with this model:

 Form TableLayout (Dock=Fill) GroupBox () FlowLayoutPanel(Dock=Fill) More controls 

And resize event:

 private void Form1_Resize(object sender, EventArgs e) { this.SuspendLayout(); this.groupBox.Width = this.Width - 20; this.groupBox.Height = this.flowLayoutPanel.GetPreferredSize(this.groupBox.Size).Height + 20; this.ResumeLayout(); } 

I hope I understand you well. At the very least, this may point you in the right direction.

+2
source

Sorry for being late to the party, but I would suggest that it would be easier for you to simply calculate the FlowLayoutPanel and its parent height than to use Arthold’s answer , as its path calls GetPreferredSize() to return a Height equal to “one row” when deleting child of the Control - even if two lines are still needed (at least in my case).

 public YodaUserControl { InitializeComponent(); InitialHeight = parentOfFlp.Height; } private int InitialHeight { get; } private void OnAdded(object sender, ControlEventArgs args) => RefreshHeight(); private void OnRemoved(object sender, ControlEventArgs args) => RefreshHeight(); private void OnSizeChanged(object sender, EventArgs args) => RefreshHeight(); private void RefreshHeight() { if (flpYoda.Controls.Count > 1 && flpYoda.Controls[0] is Control control) { parentOfFlpYoda.Height = flpYoda.Height = InitialHeight * (int)Math.Ceiling( flpYoda.Controls.Count / Math.Floor( flpYoda.ClientSize.Width / (double)control.Width)); } } 

Note:

  • Of course, you should replace YodaUserControl , parentOfFlpYoda and flpYoda with the appropriate names.
  • OnAdded , OnRemoved & OnSizeChanged must be connected to flpYoda corresponding to the ControlAdded , ControlRemoved and SizeChanged events.

If you need more help, just let me know through the comment.

0
source

All Articles