FlowLayoutPanel autowrapping doesn't work with autosize
Asked Answered
L

6

10

.NET Framework / C# / Windows Forms

I'd like the FlowLayoutPanel to automatically adjust its width or height depending on number of controls inside of it. It also should change the number of columns/rows if there is not enough space (wrap its content). The problem is that if I set autosize then the flowlayoutpanel doesn't wrap controls I insert. Which solution is the best?

Thanks!

Lapillus answered 24/9, 2009 at 11:28 Comment(2)
I'm surprised nobody replied to this one, I'm having the same problem. Bump?Bandicoot
The TableLayoutPanel may be a better solution for you - it has built in support for auto-sizing columns and rows, as well as auto-size for the whole panel.Limber
K
3

Set the FlowLayoutPanel's MaximumSize to the width you want it to wrap at. Set WrapContents = true.

Koziara answered 15/5, 2014 at 8:16 Comment(1)
setting the maximum size still needs calculationCandytuft
B
1

Have you tried using the TableLayoutPanel? It's very useful for placing controls within cells.

Biflagellate answered 17/2, 2010 at 16:9 Comment(1)
Using TableLayoutPanel a) has a completely different use case and b) is an even worse nightmare.Midsection
D
1

There is no such thing like impossible in software development. Impossible just takes longer.

I've investigated the problem. If there is really need for Flow Layout, it can be done with a bit of work. Since FlowLayoutPanel lays out the controls without particularly thinking about the number of rows/columns, but rather on cumulative width/height, you may need to keep track of how many controls you've already added. First of all, set the autosize to false, then hook your own size management logic to the ControlAdded/ControlRemoved events. The idea is to set the width and height of the panel in such a way, that you'll get your desired number of 'columns' there

Dirty proof of concept:

private void flowLayoutPanel1_ControlAdded(object sender, ControlEventArgs e)
    {
        int count = this.flowLayoutPanel1.Controls.Count;
        if (count % 4 == 0)
        {
            this.flowLayoutPanel1.Height = this.flowLayoutPanel1.Height + 70;
        }
    }

if the panel has initially width for 4 controls, it will generate row for new ones. ControlRemoved handler should check the same and decrease the panel height, or get all contained controls and place them again. You should think about it, it may not be the kind of thing you want. It depends on the usage scenarios. Will all the controls be of the same size? If not, you'd need more complicated logic.

But really, think about table layout - you can wrap it in a helper class or derive new control from it, where you'd resolve all the control placing logic. FlowLayout makes it easy to add and remove controls, but then the size management code goes in. TableLayout gives you a good mechanism for rows and columns, managing width and height is easier, but you'd need more code to change the placement of all controls if you want to remove one from the form dynamically.

Disinfectant answered 17/2, 2010 at 23:27 Comment(0)
C
1

If possible, I suggest you re-size the FlowLayoutPanel so that it makes use of all the width that is available and then anchor it at Top, Left and Right. This should make it grow in height as needed while still wrapping the controls.

Carmelacarmelia answered 26/7, 2011 at 17:26 Comment(1)
But how do you tell the FlowLayoutPanel to automatically update its Height property based on how many lines it has needed to create when wrapping content? I do like the idea of anchoring Top, Left, and Right, but the Height of my FlowLayoutPanel still seems to remain constant…Mt
H
1

I know this is an old thread but if anyone else wonders on here then here's the solution I produced - set autosize to true on the panel and call this extension method from the flow panel's Resize event:

public static void ReOrganise(this FlowLayoutPanel panel)
{
    var width = 0;
    Control prevChildCtrl = null;

    panel.SuspendLayout();

    //Clear flow breaks
    foreach (Control childCtrl in panel.Controls)
    {
        panel.SetFlowBreak(childCtrl, false);
    }

    foreach (Control childCtrl in panel.Controls)
    {
        width = width + childCtrl.Width;

        if(width > panel.Width && prevChildCtrl != null)
        {
            panel.SetFlowBreak(prevChildCtrl, true);
            width = childCtrl.Width;
        }

        prevChildCtrl = childCtrl;
    }

    panel.ResumeLayout();
}
Herisau answered 8/5, 2019 at 13:19 Comment(0)
D
0

Are you adding the controls dynamically basing on the user's actions? I'm afraid you'd need to change the FlowLayout properties on the fly in code, when adding new controls to it, then refreshing the form would do the trick.

Disinfectant answered 17/2, 2010 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.