安排FlowLayoutPanel控件以占用最少的空间

时间:2014-10-14 19:54:17

标签: c# .net flowlayoutpanel

我使用FlowLayoutPanel控件,我想知道是否还要执行控件的自动布局,以便它们占用尽可能低的空间? 例如,添加1个宽度为100px的控件,3个宽度为500px的控件和1个100px的控件。

它应该是这样的:

##Control1##
##############Control2##########################
##############Control3##########################
##############Control4##########################
##Control5##

正如你所看到的,有些空间正在被浪费,无论如何都要优化它的位置以达到这样的效果而无需手动重新定位?

##Control1## ##Control5##
##############Control2##########################
##############Control3##########################
##############Control4##########################

1 个答案:

答案 0 :(得分:2)

如何安排控件以占用最少的空间:

(顶部:初始布局,底部:结果布局)

enter image description here

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

    private void Form1_Load(object sender, EventArgs e) {
        var flowLayoutPanel = flowLayoutPanel1;
        ReorganizeFlowLayoutPanel(flowLayoutPanel);
    }

    private static void ReorganizeFlowLayoutPanel(FlowLayoutPanel flowLayoutPanel) {
        var width = flowLayoutPanel.Width;
        var controls = flowLayoutPanel.Controls.OfType<Control>().ToList();
        var ascending = new List<Control>(controls.OrderBy(s => s.Width));
        var descending = new List<Control>(controls.OrderByDescending(s => s.Width));

        var list = new List<Control>();
        while (ascending.Count > 0) {
            Control smallest = ascending[0];
            ascending.RemoveAt(0);
            if (ascending.Count == 0) {
                list.Add(smallest);
                break;
            }
            foreach (var largest in descending) {
                if (smallest.Width + largest.Width < width) {
                    list.Add(smallest);
                    list.Add(largest);
                    ascending.Remove(largest);
                    descending.Remove(largest);
                    descending.Remove(smallest);
                    break;
                }
            }
        }
        var i = 0;
        foreach (var control in list) {
            flowLayoutPanel.Controls.SetChildIndex(control, i++);
        }
    }
}

现在,您在使用时可能会遇到用户体验&#39; 问题,就像您希望其中某些问题符合特定顺序一样。解决此类问题的方法是将Control.Tag属性设置为某些字符串,例如"Priority=1""Priority=2"等等。

然后将ascending的定义替换为:

var ascending = new List<Control>(controls.OrderBy(s => s.Width).ThenBy(s=>(string)s.Tag) );

排列没有优先级标签:

enter image description here

安排优先级标记:

enter image description here

我展示的示例非常简单,您可能希望推出自己的逻辑以更好地区分控件。

注意:这是一种非常天真的方法,如果您正在寻找更复杂的算法,那么您应该从精灵表纹理制作工具中获取一些灵感,例如http://spritesheetpacker.codeplex.com/


相反:(原始答案)

您可以使用此方法以某种方式重新组织控件:

using System;
using System.Linq;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e) {
            var flowLayoutPanel = flowLayoutPanel1;
            ReorganizeFlowLayoutPanel(flowLayoutPanel);
        }

        private static void ReorganizeFlowLayoutPanel(FlowLayoutPanel flowLayoutPanel) {
            var controls = flowLayoutPanel.Controls.OfType<Control>().OrderBy(s => s.Width);
            var index = 0;
            foreach (var tuple in controls) {
                flowLayoutPanel.Controls.SetChildIndex(tuple, index++);
            }
        }
    }
}

初始布局:

enter image description here

新布局:

enter image description here

注意:它们按照发现顺序排序,即如果您不喜欢。没有。 4你必须在没有之后手动放置它。 4在重组小组之前。