Winforms FlowLayoutPanel 自适应控件去除不必要的空格

4

我有一个FlowLayoutPanel

AutoScroll = True

FlowDirection = LeftToRight

WrapContents = True

动态添加的控件具有相同的宽度,但高度自适应。所以该面板将会像this一样,其中项目之间有垂直空隙。由于行的高度由控件的最大高度管理。因此,我想要移除这些不必要的空格,最终结果将像this

如果使用FlowLayoutPanel无法实现,那么完美地完成它的正确思路是什么?


使用3个(或更多)FlowLayoutPanel。 - Alexander Petrov
您可以自己创建面板并在自定义代码中进行定位。或者按照 @AlexanderPetrov 的建议,使用 FlowDirection = TopDown 创建流式布局面板作为列。 - Otterprinz
这些是不错的想法,但我正在努力寻找更强大的解决方案。谢谢。 - Shady Boshra
3
这是一个标准的软件工程问题,“装箱问题”。即使是一维情况也是NP难问题。如果你能在O(n)时间内解决它,你就可以余生无忧了。祝你好运。 - Hans Passant
1个回答

2
  1. 这是一个矩阵,应该像处理矩阵一样处理它。
  2. 我的观点是,在这里使用PanelFlowLayoutpanel更合适。
  3. 请查看我的建议和输出,以实现这样的行为。

澄清:这段代码需要改进才能适应所有可能的情况,但您可以从中学习如何处理此类问题的基本思路。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }


    private void Form1_Load(object sender, EventArgs e)
    {
        Example();
    }

    // space beetween controls (top and right)
    public int MarginSpace = 8;
    // first element location
    public Point StartPoint = new Point(10, 10);
    private void Example()
    {
        var fixesWidth = 70;
        List<Label> randomLables = new List<Label>();
        Random rand = new Random();
        // generate lables with random heights
        for (int i = 1; i < 10; i++)
        {
            Label lr = new Label();
            var randheight = rand.Next(60, 120);
            lr.Size = new Size(fixesWidth, randheight);
            lr.Text = i.ToString();
            lr.BackColor = Color.Black;
            lr.ForeColor = Color.White;
            randomLables.Add(lr);
        }

        // check how many elements in one "column" (possible also to add right+left margin)
        var cols = panel1.Width / fixesWidth;
        // create matrix object to get locations of each label
        MyMatrix m = new MyMatrix(cols, randomLables.Count, 15, 70, StartPoint);
        m.SetMatrix(randomLables);
        int counter = 0;
        // pupulate all lables with the points from MyMatrix object
        foreach (Point p in m.pointsMatrix)
        {
            randomLables[counter].Location = p;
            panel1.Controls.Add(randomLables[counter]);
            counter++;
        }
    }
}
class MyMatrix
{
    private int Rows;
    private int TotalElements;
    private int Cols;
    private int Margin;
    private int ElementWidth;
    private Point StartPoint;
    public MyMatrix(int cols, int totalelements, int margin, int elementwidth, Point startingpoint)
    {
        this.Cols = cols;
        this.TotalElements = totalelements;
        this.Margin = margin;
        this.ElementWidth = elementwidth;
        this.StartPoint = startingpoint;

        // calculate number of rows
        Rows = totalelements / cols;
    }

    public List<Point> pointsMatrix = new List<Point>();
    int cellCounter = 0;
    public void SetMatrix(List<Label> Labels)
    {
        for (int i = 0; i < Rows; i++)
        {
            for (int j = 0; j < Cols; j++)
            {

                var x = StartPoint.X + j * (Margin + ElementWidth);
                var y = StartPoint.Y;
                if (cellCounter >= Cols)
                {
                    // find the parallel cell in the row above
                    y = pointsMatrix[cellCounter - Cols].Y + Labels[cellCounter - Cols].Height + Margin;
                }
                else
                {
                    // do nothing it is first row
                }

                Point p = new Point(x, y);
                pointsMatrix.Add(p);
                cellCounter += 1;
            }
        }
    }
}

输出:
在此输入图片描述


你做到了,伙计。谢谢。我只是稍微编辑了一下,但解决方案是你提供的。 - Shady Boshra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接