FlowLayoutPanel使用AutoSize时的高度错误

时间:2011-10-04 11:35:35

标签: c# winforms groupbox flowlayoutpanel form-layout

我有一个表格,其中包含一个包含1列和3行的TableLayout,其中包含2个FlowLayoutPanel和一个文本框。 所有行都是AutoSize,列设置为百分比= 100%。

每个FlowLayoutPanel都包含多个TextBox。 FlowLayoutPanels设置为:LeftToRight,AutoSize = true,GrowAndShrink,Docking = Fill。

大纲是:

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)

问题是如果我将FlowLayoutPanel放在GroupBox中并且也设置为AutoSize = true,则FlowLayoutPanel高度未正确设置,并且它在一行中显示TextBoxes,从表单中剪切一些TextBox。

大纲是:

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)
顺便说一句,如果我使用GroupBox,Panel或者甚至是UserControl来保存FlowLayoutPanel,也会发生同样的事情。

BTW 2,即使没有TableLayout也会发生这种情况。我尝试将GroupBox(带有FlowLayoutPanel)放在AutoSized表单上,我得到了相同的行为。

我认为问题在于当FlowLayoutPanel位于另一个也是AutoSized的容器中时,它无法传递给它的容器是首选大小。

可以做些什么来覆盖这个错误?

请帮忙 谢谢, 约拉姆


p.s:我必须使用GroupBox在TextBoxes周围有一个漂亮的框架。

3 个答案:

答案 0 :(得分:2)

当您将FlowLayoutPanel停靠在GroupBox(或其他容器)中时,您也可以离开AutoSize=false。我不确定,但这可能会使群组在调整大小时成为“领先”控制。


修改(在您发表评论后)

'领先控制'是我试图表达组框大小将决定FLP的那个,这不是一些官方术语。问题是对接和自动调整是fighting one another by nature,有人应该采取控制。这只能在减少对接和自动调整时以及通过自己编写调整大小事件来完成。

在玩了一下之后我终于想出了这个模型:

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

调整大小事件:

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

我希望我能理解你。至少这可能会指向正确的方向。

答案 1 :(得分:2)

也遇到过这个问题,并试图找出如何轻松解决这个问题。 尽管@ GertArnold的回答确实有所帮助,但感觉有点麻烦,我寻找另一种解决方案。

我发现Flow Panel的自动调整逻辑正在处理'最小'要求,并且通过添加一个空白面板,最小高度我可以强制Flow Panel的宽度,从而使所有其他子控件成为可见。

所以在上面的例子中,最终的布局是:

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)

希望这有帮助。

答案 2 :(得分:0)

很抱歉参加聚会晚了,但我建议与Gert Arnold's answer相比,对FlowLayoutPanel及其父辈的身高进行简单的计算比使用{{3}}更好。导致GetPreferredSize()在删除子级Height时返回等于“单行”的Control-即使仍然需要两行(至少在我的情况下)。

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

注释:

  • 当然,您必须用相应的名称替换YodaUserControlparentOfFlpYodaflpYoda
  • OnAddedOnRemovedOnSizeChanged必须附加到与flpYodaControlAddedControlRemoved事件相对应的SizeChanged个。

如果您需要进一步的帮助,请通过评论告知我。