FlowLayoutPanel shows a horizontal scrollbar with inner pane width equal to client size width

I am having a problem with a FlowLayoutPanel while its children are being resized in the FlowLayoutPanel ClientSizeChanged event.

I am trying to resize users horizontally when the FlowLayoutPanel changes. The problem is that even if the margin of the child is 0 and the padding of the FlowLayoutPanel is also 0, after the ClientSizeChanged event handler is executed, the FlowLayoutPanel shows its horizontal scrollbar , while the width of the child is exactly the same as FlowLayoutPanel.ClientSize.Width .

I tried to move the code to the Resize event, but I still get the same result.

This is an example demonstrating the problem, there is one FlowLayoutPanel with the following properties changed by default:

  • AutoScroll = true
  • FlowDirection = TopDown
  • Margin = 0,0,0,0
  • Name = flow1
  • BackColor = Red

The FlowLayoutPanel also has a regular panel:

  • Margin = 0,0,0,0
  • Name = panel1
  • BackColor: blue

And finally, an interval timer of 1 that changes the width of the FlowLayoutPanel and turns itself off when the HorizontalScroll.Visibile property of the FlowLayoutPanel is true and shows a message box that declares the width of the panel1 and the ClientSize.Width of the flow1.

Here's the code:

    private void timer1_Tick(object sender, EventArgs e)
    {
        flow1.Width -= 1;

        if (flow1.HorizontalScroll.Visible)
        {
            timer1.Enabled = false;
            MessageBox.Show("Panel.Width = " + panel1.Width.ToString() +
                ", FlowPanel.ClientWidth = " + flow1.ClientSize.Width.ToString());
        }
    }

    private void flow1_ClientSizeChanged(object sender, EventArgs e)
    {
        panel1.Width = flow1.ClientSize.Width;
    }

      

What is the logic behind the horizontal scrollbar as long as the kids don't overflow the client size? And most importantly, how to prevent it?

+3


source to share


1 answer


This is an event ordering problem, the layout is calculated too early. Auto layout has some nasty corner cabinets, it can also be bistable when the layout is flipped back and forth between two solutions. You can see this in your test app, add it flow1.PerformLayout();

before the MessageBox.Show () call and you can see the scrollbar is hidden again.

This is why there is a method SuspendLayout()

. Winforms programmers don't use it enough. For a good reason, it's pretty hard to judge when you need it. And they really don't want it. The general rule of thumb is that you should use it if the layout has to deal with more than one resizing.

What's the true fix in your test program:



private void timer1_Tick(object sender, EventArgs e) {
    flow1.SuspendLayout();
    flow1.Width -= 1;
    flow1.ResumeLayout(true);
    // etc..
}

      

And you will see that it works fine now, you will never see the message box.

+1


source







All Articles