【发布时间】:2009-11-12 19:22:38
【问题描述】:
有没有一种优雅的方式来做到这一点?也许与 Linq 一起使用?
对于这样的事情:
List<ControlCollection> list = { ... }
List<Control> merged = list.MergeAll();
编辑:从某种意义上说,最终集合将是一维的,所有控件都将存在,而不是嵌套。
【问题讨论】:
标签: c# .net linq collections
有没有一种优雅的方式来做到这一点?也许与 Linq 一起使用?
对于这样的事情:
List<ControlCollection> list = { ... }
List<Control> merged = list.MergeAll();
编辑:从某种意义上说,最终集合将是一维的,所有控件都将存在,而不是嵌套。
【问题讨论】:
标签: c# .net linq collections
这个怎么样:
public static void Append(this System.Windows.Forms.Control.ControlCollection collection, System.Windows.Forms.Control.ControlCollection newCollection)
{
Control[] newControl = new Control[newCollection.Count];
newCollection.CopyTo(newControl, 0);
collection.AddRange(newControl);
}
用法:
Form form1 = new Form();
Form form2 = new Form();
form1.Controls.Append(form2.Controls);
这将使控制树变平:
public static void FlattenAndAppend(this System.Windows.Forms.Control.ControlCollection collection, System.Windows.Forms.Control.ControlCollection newCollection)
{
List<Control> controlList = new List<Control>();
FlattenControlTree(collection, controlList);
newCollection.AddRange(controlList.ToArray());
}
public static void FlattenControlTree(System.Windows.Forms.Control.ControlCollection collection, List<Control> controlList)
{
foreach (Control control in collection)
{
controlList.Add(control);
FlattenControlTree(control.Controls, controlList);
}
}
【讨论】:
new Control[newCollection.Count]不是更容易吗?
Linq 有 Concat 和 Union 方法。是您正在寻找的其中之一吗?
【讨论】:
ToList() 即可获得List<Control>。
树扩展方法
static class TreeExtensions
{
public static IEnumerable<R>TraverseDepthFirst<T, R>(
this T t,
Func<T, R> valueselect,
Func<T, IEnumerable<T>> childselect)
{
yield return valueselect(t);
foreach (var i in childselect(t))
{
foreach (var item in i.TraverseDepthFirst(valueselect, childselect))
{
yield return item;
}
}
}
}
用法:
Control c = root_form_or_control;
var allcontrols = c.TraverseDepthFirst(
x => x,
x => x.Controls.OfType<Control>())).ToList();
【讨论】:
var merged = (from cc in list
from Control control in cc
select cc)
.ToList();
或(与显式 LINQ 方法调用相同):
var merged = list.SelectMany(cc => cc.Cast<Control>()).ToList();
[EDIT]反映新添加的嵌套要求:
static IEnumerable<T> FlattenTree<T>(
this IEnumerable<T> nodes,
Func<T, IEnumerable<T>> childrenSelector)
{
foreach (T node in nodes)
{
yield return node;
foreach (T child in childrenSelector(node))
{
yield return child;
}
}
}
var merged = list.SelectMany(cc => cc.Cast<Control>())
.FlattenTree(control => control.Controls.Cast<Control>())
.ToList();
【讨论】: