Can I evaluate two groups of elements with a foreach loop in C # winforms?

I have winforms TabControl, and I'm trying to iterate over all the controls contained in each tab. Is there a way to add and to the foreach or is it impossible to evaluate more than one group of elements? For example, this is what I would like to do:

 foreach (Control c in tb_Invoices.Controls and tb_Statements.Controls) { //do something } 

OR

 foreach (Control c in tb_Invoices.Controls, tb_Statements.Controls) { //do something } 

Is this possible, and if not, which is better? Do I need to use a for loop?

+6
source share
6 answers
 foreach(TabPage page in yourTabControl.TabPages){ foreach(Control c in page.Controls){ LoopThroughControls(c); } } private void LoopThroughControls(Control parent){ foreach(Control c in parent.Controls) LoopThroughControls(c); } 
+4
source

Final decision:

 var allControls = from TabPage p in tabControl.TabPages from Control c in p.Controls select c; 

Original answer - use Concat :

 var allControls = tb_Invoices.Controls.Cast<Control>() .Concat(tb_Statements.Controls.Cast<Control>(); 

BTW I think it's better to use a simple non generic ArrayList here

 ArrayList allControls = new ArrayList(); allControls.AddRange(tb_Invoices.Controls); allControls.AddRange(tb_Statements.Controls); 
+3
source

What I like to do:

 var list = new List<T>(); list.AddRange(list1); list.AddRange(list2); list.AddRange(list3); list.AddRange(list4); foreach (T item in list) { ..... } 
0
source

You can use one foreach loop, writing it recursively. This will ensure that all controls of all types in your form go through.

 private void LoopAllControls(Control YourObject) foreach(Control c in YourObject.Controls) { if(C.Controls.Count > 0) LoopAllControls(c.Controls); //your code } 
0
source

You can do:

 public static void ForAllChildren(Action<Control> action, params Control[] parents) { foreach(var p in parents) foreach(Control c in p.Controls) action(c); } 

Called as:

 ForAllChildren(x => Foo(x), tb_Invoices, tb_Statements); 

You may have suffered a little from performance for invoking an action, although in this case you could just use a nested foreach :

 foreach (var p in new Control[] { tb_Invoices, tb_Statements }) foreach (Control c in p.Controls) Foo(c); 

Similarly, a general solution for cyclic switching all elements in any nonequivalent IEnumerable could be (although a bit like using a sledgehammer to drive a nail):

 public static void ForEachAll<T>(Action<T> action, params System.Collections.IEnumerable[] collections) { foreach(var collection in collections) foreach(var item in collection.Cast<T>()) action(item); } 

Called as:

 ForEachAll<Control>(x => Foo(x), tb_Invoices.Controls, tb_Statements.Controls); 
0
source

If you cannot use LINQ (e.g. bound to .NET2), I suggest you use this method:

 public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] args) { foreach (IEnumerable<T> collection in args) { foreach (T item in collection) { yield return item; } } } 

Now you have a common function that you can use with any enumerated. Your loop may look like this:

 foreach (Control c in Concat(tb_Invoices.Controls, tb_Statements.Controls)) { //do something } 

Simple, cheap and expressive!

EDIT: if your collection does not implement IEnumerable<T> , but only IEnumerable , you can add an overload that will accept the latter. Everything remains unchanged, except that T changes to object in a nested loop.

0
source

Source: https://habr.com/ru/post/951221/


All Articles