【问题标题】:FlowLayoutPanel autowrapping doesn't work with autosizeFlowLayoutPanel 自动换行不适用于 autosize
【发布时间】:2019-05-08 21:19:39
【问题描述】:

.NET 框架/C#/Windows 窗体

我希望 FlowLayoutPanel 根据其内部控件的数量自动调整其宽度或高度。如果没有足够的空间(包装其内容),它还应该更改列/行数。问题是,如果我设置自动大小,那么 flowlayoutpanel 不会包装我插入的控件。哪种解决方案最好?

谢谢!

【问题讨论】:

  • 我很惊讶没有人回复这个问题,我也遇到了同样的问题。撞?
  • TableLayoutPanel 对您来说可能是一个更好的解决方案 - 它内置了对自动调整列和行大小以及整个面板大小的支持。

标签: c# winforms flowlayoutpanel


【解决方案1】:

将 FlowLayoutPanel 的 MaximumSize 设置为您希望它换行的宽度。设置 WrapContents = true。

【讨论】:

  • 设置最大尺寸仍需计算
【解决方案2】:

您是否尝试过使用 TableLayoutPanel?这对于在单元格中放置控件非常有用。

【讨论】:

  • 使用 TableLayoutPanel a) 有一个完全不同的用例,b) 是更糟糕的噩梦。
【解决方案3】:

在软件开发中没有不可能的事情。不可能,只是需要更长的时间。

我已经调查了这个问题。如果真的需要 Flow Layout,可以通过一些工作来完成。由于 FlowLayoutPanel 布局控件时没有特别考虑行数/列数,而是考虑累积宽度/高度,因此您可能需要跟踪已添加的控件数量。首先,将 autosize 设置为 false,然后将您自己的大小管理逻辑挂钩到 ControlAdded/ControlRemoved 事件。这个想法是以这样一种方式设置面板的宽度和高度,您将在那里获得所需数量的“列”

概念证明:

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

如果面板最初有 4 个控件的宽度,它将为新控件生成行。 ControlRemoved 处理程序应检查相同并降低面板高度,或获取所有包含的控件并重新放置它们。你应该考虑一下,它可能不是你想要的那种东西。这取决于使用场景。所有控件的大小是否相同?如果没有,你需要更复杂的逻辑。

但实际上,请考虑表格布局 - 您可以将其包装在帮助类中或从中派生新控件,您可以在其中解决所有控件放置逻辑。 FlowLayout 使添加和删除控件变得容易,但随后会添加大小管理代码。 TableLayout 为您提供了良好的行和列机制,管理宽度和高度更容易,但您需要更多代码来更改所有控件的位置控制是否要从表单中动态删除一个。

【讨论】:

    【解决方案4】:

    如果可能,我建议您重新调整 FlowLayoutPanel 的大小,以便它利用所有可用的宽度,然后将其锚定在顶部、左侧和右侧。这应该使它的高度根据需要增加,同时仍然包裹控件。

    【讨论】:

    • 但是您如何告诉FlowLayoutPanel 根据包装内容时需要创建的行数自动更新其Height 属性?我确实喜欢锚定顶部、左侧和右侧的想法,但我的 FlowLayoutPanelHeight 似乎仍然保持不变……
    【解决方案5】:

    我知道这是一个旧线程,但如果其他人对此感到疑惑,那么这就是我制作的解决方案 - 在面板上将 autosize 设置为 true 并从流程面板的 Resize 事件中调用此扩展方法:

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

    【讨论】:

      【解决方案6】:

      您是否根据用户的操作动态添加控件?恐怕您需要在代码中动态更改 FlowLayout 属性,向其中添加新控件时,然后刷新表单就可以了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多