FlowLayoutPanel显示水平滚动条,内部​​面板的宽度与客户端大小宽度相同

时间:2015-05-20 06:37:16

标签: c# resize scrollbar flowlayoutpanel

我在FlowLayoutPanel的ClientSizeChanged事件中调整子项大小时遇到​​FlowLayoutPanel问题。

当FlowLayoutPanel调整大小时,我试图让孩子们水平调整大小。问题是,即使子节点的边距为0并且FlowLayoutPanel的填充也为0,在执行ClientSizeChanged事件处理程序之后,FlowLayoutPanel会显示其水平滚动条 ,而子节点的宽度为与FlowLayoutPanel.ClientSize.Width完全相同

我已尝试将代码移至Resize事件,但我仍然得到相同的结果。

这是一个演示问题的示例,其中一个FlowLayoutPanel具有以下属性从默认值更改:

  • AutoScroll = true
  • FlowDirection = TopDown
  • 保证金= 0,0,0,0
  • 名称= flow1
  • BackColor =红色

还有FlowLayoutPanel内的常规面板:

  • 保证金= 0,0,0,0
  • 名称= panel1
  • BackColor:Blue

最后,一个间隔为1的计时器改变FlowLayoutPanel的宽度并在FlowLayoutPanel的Horizo​​ntalScroll.Visibile属性为true时禁用自身,并显示一个消息框,该消息框宣告了flow1的panel1和ClientSize.Width的宽度

以下是代码:

    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;
    }

当没有孩子溢出客户端大小时,显示水平滚动条背后的逻辑是什么?最重要的是,如何防止它发生?

1 个答案:

答案 0 :(得分:1)

这是一个事件订单问题,布局过早计算。自动布局有几个讨厌的角落情况,它也可以是双稳态的,布局在两个解决方案之间来回翻转。您可以在测试应用中看到这一点,在MessageBox.Show()调用之前添加flow1.PerformLayout();,您将看到滚动条再次被隐藏。

这就是SuspendLayout()方法存在的原因。 Winforms程序员不能充分利用它。有充分理由,很难判断您何时需要它。他们真的不想要它。基本规则是,如果布局必须处理多个大小更改,则应使用它。

您的测试计划中真正的解决方法是什么:

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

你现在看到它工作正常,你永远不会看到消息框。