Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive control search with LINQ

If I wanted to find checked check boxes on an ASP.NET page I could use the following LINQ query.

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

That works fine if the checkboxes are nested in the current control collection, but I'd like to know how to extend the search by drilling down into the control collections of the top-level controls.

The question was asked here:

Finding controls that use a certain interface in ASP.NET

And received non-LINQ answers, I already have my own version of a recursive control search on type and ID as extension methods, but I just wondered how easy this is to do in LINQ?

like image 537
PhilGriffin Avatar asked Oct 31 '08 15:10

PhilGriffin


2 Answers

Take the type/ID checking out of the recursion, so just have a "give me all the controls, recursively" method, e.g.

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;         }     } } 

That's somewhat inefficient (in terms of creating lots of iterators) but I doubt that you'll have a very deep tree.

You can then write your original query as:

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

(EDIT: Changed AllControls to GetAllControls and use it properly as a method.)

like image 175
Jon Skeet Avatar answered Sep 27 '22 21:09

Jon Skeet


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; } 

Now based on the above function, we can do something like this:

public static Control FindControl(this Control container, string Id) {     var child = container.AllControls().FirstOrDefault(c => c.ID == Id);     return child; } 
like image 39
Arthur Dzhelali Avatar answered Sep 27 '22 19:09

Arthur Dzhelali