用LINQ进行recursion控制search

如果我想在ASP.NET页面上查找checkbox,我可以使用下面的LINQ查询。

var checkBoxes = this.Controls .OfType<CheckBox>() .TakeWhile<CheckBox>(cb => cb.Checked); 

如果checkbox嵌套在当前的控件集合中,那么工作正常,但我想知道如何通过深入到顶层控件的控件集合来扩展search。

问题在这里被问到:

查找在ASP.NET中使用特定接口的控件

并收到非LINQ的答案,我已经有了我自己的types和ID作为扩展方法的recursion控制search版本,但我只是想知道在LINQ中这是多么容易做?

把recursiontypes/ ID检查出来,所以只要有一个“给我所有的控制,recursion”的方法,例如

 public static IEnumerable<Control> GetAllControls(this Control parent) { foreach (Control control in parent.Controls) { yield return control; foreach(Control descendant in control.GetAllControls()) { yield return descendant; } } } 

这有点低效(就创build大量的迭代器而言),但我怀疑你会有一个非常深的树。

然后,您可以将原始查询写为:

 var checkBoxes = this.GetAllControls() .OfType<CheckBox>() .TakeWhile<CheckBox>(cb => cb.Checked); 

(编辑:更改AllControls GetAllControls并正确使用它作为一种方法。)

 public static IEnumerable<Control> AllControls(this Control container) { //Get all controls var controls = container.Controls.Cast<Control>(); //Get all children var children = controls.Select(c => c.AllControls()); //combine controls and children var firstGen = controls.Concat(children.SelectMany(b => b)); return firstGen; } 

现在基于上面的function,我们可以做这样的事情:

 public static Control FindControl(this Control container, string Id) { var child = container.AllControls().FirstOrDefault(c => c.ID == Id); return child; } 

我build议使AllControlsrecursion是:

  public static IEnumerable<Control> AllControls(this Control parent) { foreach (Control control in parent.Controls) { yield return control; } foreach (Control control in parent.Controls) { foreach (Control cc in AllControls(control)) yield return cc; } } 

第二个foreach看起来很奇怪,但这是我知道“扁平化”recursion调用的唯一方法。