使用 AutoSize 时的 FlowLayoutPanel 高度错误

发布于 2024-12-08 09:08:26 字数 1417 浏览 5 评论 0 原文

我有一个包含 1 列和 3 行的 TableLayout 的表单,其中包含 2 个 FlowLayoutPanel 和一个文本框。 所有行均为 AutoSize,列设置为 Percentage=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 放置在也设置为 AutoSize=true 的 GroupBox 中,则 FlowLayoutPanel 高度设置不正确,并且它显示文本框为 1 行,将一些文本框从表单中删除。

大纲是:

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,也会发生同样的事情。

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

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

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

请帮忙 谢谢, Yoram


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

I have a form holding a TableLayout with 1 column and 3 rows that holds 2 FlowLayoutPanels and a Text box.
All Rows are AutoSize, and the column is set to Percentage=100%.

Each FlowLayoutPanel holds several TextBoxes.
The FlowLayoutPanels are set: LeftToRight, AutoSize=true, GrowAndShrink, Docking=Fill.

The outline is:

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 if I place the FlowLayoutPanel inside a GroupBox which are also set to be AutoSize=true, the FlowLayoutPanel Height are not set correctly and it shows the TextBoxes in 1 line cutting some TextBoxes out of the form.

The outline is:

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)

BTW,the same thing happens if I use instead of a GroupBox, a Panel or even a UserControl to hold the FlowLayoutPanel.

BTW 2, this happens even without the TableLayout. I tried placing the GroupBox (with the FlowLayoutPanel) on an AutoSized Form and I get the same behavior.

What I think the problem is that when the FlowLayoutPanel is in another container that is also AutoSized it fails to pass to it's container is preferred size.

What can be done to override this bug??

Please help
Thanks,
Yoram


p.s: I must use the GroupBox to have a nice frame around the TextBoxes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你的心境我的脸 2024-12-15 09:08:26

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

我发现流程面板的自动调整大小逻辑正在满足“最小”要求,并且通过添加最小高度的空白面板,我能够强制流程面板的宽度,从而使所有其他子控件可见。

因此,在上面的示例中,最终布局将是:

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)

希望这会有所帮助。

Had encountered this problem too, and tried to figure out how to easily resolve this.
Although the @GertArnold's answer did help, it felt a bit cumbersome, and I searched for another solution.

What I found was that the Flow Panel's autosize logic was working on the 'minimum' requirements, and by adding a blank Panel, of minimum height I was able to force the Flow Panel's width, thus making all other child controls to be visible.

so in the example above the final layout would be:

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.

笑叹一世浮沉 2024-12-15 09:08:26

当您将 FlowLayoutPanel 停靠在 GroupBox(或其他容器)中时,您也可以保留它们的 AutoSize=false。我不确定,但这可能会使组合框成为调整大小时的“领先”控件。


编辑(在您的评论之后)

“领先控制”是我的话,试图表达组框大小将决定 FLP 的大小,这不是一些官方术语。问题是对接和自动调整大小是 本质上是互相争斗,应该有人来控制。这只能在减少对接和自动调整大小并自行编程调整大小事件时才能完成。

经过一番尝试后,我终于想出了这个模型:

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

我希望我能很好地理解你。至少这可能会为您指明正确的方向。

As you dock the FlowLayoutPanel in the GroupBox (or other containers), you may as well leave their AutoSize=false. I'm not sure, but this may make the groupbox the 'leading' control when it comes to sizing.


Edit (after your comment)

'Leading control' are my words trying to express that groupbox size would determine that of the FLP, it's not some official term. The problem is that docking and autosizing are fighting one another by nature and someone should take, well, control. Which can only be done when docking and autosizing are cut back and by programming the resize events yourself.

After playing around a bit I finally came up with this model:

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

And the 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 understood you well. At least this may point you in the right direction.

三五鸿雁 2024-12-15 09:08:26

抱歉迟到了,但我建议您最好对 FlowLayoutPanel 及其父级高度进行简单计算,而不是使用 格特·阿诺德的回答,因为他的方式导致GetPreferredSize() 在删除子 Control 时返回等于“单行”的 Height - 即使仍然需要两行(在至少就我而言)。

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 替换为您相应的名称。
  • OnAddedOnRemoved & OnSizeChanged需要附加到flpYoda对应的ControlAddedControlRemoved & SizeChanged 事件。

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

Sorry for being late to the party, but I'd like to suggest that you're better off with a simple calculation of the FlowLayoutPanels and its parent's height than using Gert Arnold's answer as his way causes GetPreferredSize() to return a Height equal to "single row" upon deleting a child Control - even if two rows would still be required (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));
  }
}

Notes:

  • Of course, you have to replace YodaUserControl, parentOfFlpYoda and flpYoda with your corresponding names.
  • OnAdded, OnRemoved & OnSizeChanged need to be attached to flpYodas corresponding ControlAdded, ControlRemoved & SizeChanged events.

If you need further assistance, just let me know via a comment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文