首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在FlowLayoutPanel中对多行控件进行居中

在FlowLayoutPanel中对多行控件进行居中
EN

Stack Overflow用户
提问于 2019-02-05 19:58:09
回答 1查看 2.2K关注 0票数 5

我正在尝试制作一个面板,它可以承载动态添加的控件。有两个注意事项:

  • 将会有很多控件,因此面板应该在达到宽度限制并垂直滚动时将元素包装成新的行。
  • 控件的大小可以更改,这将改变元素的数量。 可以放进一排的。

我看到了一些以一种形式提出的中心化动态控件的解决方案,并基于以下原因拒绝了这些解决方案:

  • TableLayoutPanel -我使用它的主要问题是元素增长时发生的事件,并且必须从3-2网格转移到2-4,因为TableLayoutPanel似乎不能很好地处理这些问题。
  • AutoSize FlowLayoutPanel,它可以在TableLayoutControl中生长和缩小--这个解决方案的主要问题是它只在表单中的一行中间,一旦它包装到一个新的行,元素就开始对齐到右边。我想我可以动态地将新的FlowLayoutPanels添加到TableLayoutControl的新行中,但接下来我遇到了一个类似的问题,在第一个场景中,如果元素的大小增长/缩小,需要在它们之间手动重新分配元素。

我想知道我是否缺少了一些功能,可以帮助我处理增长/收缩事件而不创建我自己的TableLayoutPanel变体?

编辑:

以下是功能草案:

  • 以面板为中心的a-两个元素
  • 添加第三个元素,这三个元素都是居中的。
  • 添加、包装到新行并居中的第四个元素。
  • D-元素扩大,现在包装到第二个元素,居中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-07 01:31:32

下面是一个复制您描述的行为的示例。

它使用一个承载多个TableLayoutPanel的FlowLayoutPanels。

一个重要的细节是子FlowLayoutPanels的锚定:它们需要锚定到顶部底部的:这将导致面板位于TableLayoutPanel行的中心。

注意,在表单构造函数中,一个RowStyles被删除。这也是非常重要的:TLP (它是非常古怪的家伙),即使你只有一列(或一列,同样的东西),也会保留2 RowStyles。第二种样式将应用于您添加的第一排,只适用于第一种,而不是其他:这会使布局变得一团糟。

另一个异常,它没有提供移除行的方法,所以我做了一个。它的功能,但基本,需要扩展,包括进一步的验证。

请参阅有关当前功能的图形示例。如果在实现其他方面需要帮助,请留下评论。

若要构建此控件,请将以下控件添加到窗体(此处,称为FLPTest1):)

  1. 添加一个面板,设置Dock.Bottom。右击和SendToBack()
  2. 添加一个tlp1),集(这里称为TableLayoutPanel集: )
    • AutoScroll = trueAutoSize = true
    • AutoSizeMode = GrowAndShrinkDock.Fill
    • 保持1列,设置为AutoSize,1行设置为AutoSize

  3. 添加一个flp1),(这里称为FlowLayoutPanel ),位于TableLayoutPanel中。实际上,这并不是必要的,只是对于这个示例代码
    • 将其锚固设置为Top, Bottom <= --这是!important,如果没有它,布局将无法正常工作:它允许FLPTLP行中居中,
    • AutoSize = trueAutoSizeMode = GrowAndShrink

  4. 添加按钮(称为btnAddControl) )
  5. 添加第二个按钮(称为btnRemoveControl) )
  6. 添加一个chkRandom) (称为CheckBox )
  7. 将代码粘贴到表单的代码文件中

代码语言:javascript
复制
using System.Drawing;
using System.Linq;
using System.Windows.Forms;


public partial class TLPTest1 : Form
{
    public TLPTest1()
    {
        InitializeComponent();
        tlp1.RowStyles.RemoveAt(1);
    }

    private void TLPTest1_Load(object sender, EventArgs e)
    {
        PictureBox pBox = new PictureBox() {
            Anchor = AnchorStyles.None,
            BackColor = Color.Orange,
            MinimumSize = new Size(125, 125),
            Size = new Size(125, 125),
        };
        flp1.Controls.Add(pBox);
        tlp1.Controls.Add(flp1);
    }

    Random rnd = new Random();
    Size[] sizes = new Size[] { new Size(75, 75), new Size(100, 100), new Size(125, 125)};
    Color[] colors = new Color[] { Color.Red, Color.LightGreen, Color.YellowGreen, Color.SteelBlue };
    Control selectedObject = null;

    private void btnAddControl_Click(object sender, EventArgs e)
    {
        Size size = new Size(125, 125);
        if (chkRandom.Checked) size = sizes[rnd.Next(sizes.Length)];
        
        var pBox = new PictureBox() {
            Anchor = AnchorStyles.None,
            BackColor = colors[rnd.Next(colors.Length)],
            MinimumSize = size,
            Size = size
        };

        bool drawborder = false;
        // Just for testing - use standard delegates instead of Lambdas in real code
        pBox.MouseEnter += (s, evt) => { drawborder = true;  pBox.Invalidate(); };
        pBox.MouseLeave += (s, evt) => { drawborder = false; pBox.Invalidate(); };
        pBox.MouseDown += (s, evt) => { selectedObject = pBox;  pBox.Invalidate(); };
        pBox.Paint += (s, evt) => { if (drawborder) {
            ControlPaint.DrawBorder(evt.Graphics, pBox.ClientRectangle, 
                                    Color.White, ButtonBorderStyle.Solid);
            }
        };

        var ctl = tlp1.GetControlFromPosition(0, tlp1.RowCount - 1);
        int overallWith = ctl.Controls.OfType<Control>().Sum(c => c.Width + c.Margin.Left + c.Margin.Right);
        overallWith += (ctl.Margin.Right + ctl.Margin.Left);

        if ((overallWith + pBox.Size.Width + pBox.Margin.Left + pBox.Margin.Right) >= tlp1.Width) {
            var flp = new FlowLayoutPanel() {
                Anchor = AnchorStyles.Top | AnchorStyles.Bottom,
                AutoSize = true,
                AutoSizeMode = AutoSizeMode.GrowAndShrink,
            };

            flp.Controls.Add(pBox);

            tlp1.SuspendLayout();
            tlp1.RowCount += 1;
            tlp1.Controls.Add(flp, 0, tlp1.RowCount - 1);
            tlp1.ResumeLayout(true);
        }
        else {
            ctl.Controls.Add(pBox);
        }
    }

    private void btnRemoveControl_Click(object sender, EventArgs e)
    {
        if (selectedObject is null) return;
        Control parent = selectedObject.Parent;
        selectedObject.Dispose();

        if (parent?.Controls.Count == 0) {
            TLPRemoveRow(tlp1, parent);
            parent.Dispose();
        }
    }

    private void TLPRemoveRow(TableLayoutPanel tlp, Control control)
    {
        int ctlPosition = tlp.GetRow(control);
        if (ctlPosition < tlp.RowCount - 1) {
            for (int i = ctlPosition; i < tlp.RowCount - 1; i++) {
                tlp.SetRow(tlp.GetControlFromPosition(0, i + 1), i);
            }
        }
        tlp.RowCount -= 1;
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54542104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档