我使用FlowLayoutPanel控件,我想知道是否有任何方法来执行控件的自动布局,以便它们占用尽可能低的空间?例如,添加一个宽度为100 and的控件,三个宽度为500 and的控件,再添加一个宽度为100 and的控件。
它应该是这样的:
##Control1##
##############Control2##########################
##############Control3##########################
##############Control4##########################
##Control5##正如你所看到的,一些空间正在被浪费,是否有优化它的位置来实现这样的东西而不手动重新定位?
##Control1## ##Control5##
##############Control2##########################
##############Control3##########################
##############Control4##########################发布于 2014-10-15 18:40:15
如何安排控件以占用最少的空间:
(顶部:初始布局,底部:结果布局)

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++);
}
}
}现在,您可能会在使用它时遇到“用户体验”问题,就像您期望它们中的一些处于特定的顺序一样。要解决这样的问题,您可以做的是将Control.Tag属性设置为某些字符串,如"Priority=1"、"Priority=2"等.
然后将ascending的定义替换为:
var ascending = new List<Control>(controls.OrderBy(s => s.Width).ThenBy(s=>(string)s.Tag) );
没有优先级标签的排列:

带有优先级标签的排列:

我已经演示过的示例非常简单,您可能希望使用自己的逻辑来更好地区分您的控件。
注:--这是一种非常天真的方法,如果您正在寻找一种更复杂的算法,那么您应该从雪碧片纹理制造商(如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++);
}
}
}
}初始布局:

新布局:

注意:它们是按发现的顺序排序的,也就是说,如果您想在4号之后选择3号,那么在重新组织面板之前,您必须手动将其放在4号之后。
https://stackoverflow.com/questions/26369210
复制相似问题