Могу ли я оценить две группы элементов с циклом foreach в C# winforms?
у меня есть WinForms TabControl, и я пытаюсь выполнить цикл через все элементы управления, содержащиеся в каждой вкладке. Есть ли способ добавить and
на foreach
цикл или невозможно оценить более одной группы элементов? Например, это то, что я хотел бы сделать:
foreach (Control c in tb_Invoices.Controls and tb_Statements.Controls)
{
//do something
}
или
foreach (Control c in tb_Invoices.Controls, tb_Statements.Controls)
{
//do something
}
возможно ли это, и если нет, то это следующая лучшая вещь? Мне нужно использовать for
петли?
6 ответов
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);
}
окончательное решение:
var allControls = from TabPage p in tabControl.TabPages
from Control c in p.Controls
select c;
оригинальный ответ - использовать Concat
:
var allControls = tb_Invoices.Controls.Cast<Control>()
.Concat(tb_Statements.Controls.Cast<Control>();
кстати, я думаю, что лучше использовать простой не общий ArrayList
здесь
ArrayList allControls = new ArrayList();
allControls.AddRange(tb_Invoices.Controls);
allControls.AddRange(tb_Statements.Controls);
что мне нравится делать, так это:
var list = new List<T>();
list.AddRange(list1);
list.AddRange(list2);
list.AddRange(list3);
list.AddRange(list4);
foreach (T item in list)
{
.....
}
вы можете использовать один цикл foreach, написав его рекурсивно. Это позволит перебрать все элементы управления всех типов в форме.
private void LoopAllControls(Control YourObject)
foreach(Control c in YourObject.Controls)
{
if(C.Controls.Count > 0)
LoopAllControls(c.Controls);
//your code
}
вы могли бы сделать:
public static void ForAllChildren(Action<Control> action,
params Control[] parents)
{
foreach(var p in parents)
foreach(Control c in p.Controls)
action(c);
}
называется так:
ForAllChildren(x => Foo(x), tb_Invoices, tb_Statements);
вы можете быть немного поражены производительностью для вызова действия, хотя в этом случае вы можете просто использовать вложенный foreach
:
foreach (var p in new Control[] { tb_Invoices, tb_Statements })
foreach (Control c in p.Controls)
Foo(c);
аналогично, универсального решения для перебора всех элементов в любой необщего IEnumerable
может быть (хотя немного похоже на использование кувалды для забивания гвоздя):
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);
}
называется так:
ForEachAll<Control>(x => Foo(x), tb_Invoices.Controls, tb_Statements.Controls);
если вы не в состоянии использовать LINQ (например, застрял .NET2), я предлагаю вам использовать этот метод:
public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] args)
{
foreach (IEnumerable<T> collection in args)
{
foreach (T item in collection)
{
yield return item;
}
}
}
теперь у вас есть общая функция, которую вы можете использовать с что-нибудь вот перечисли. Ваш цикл может выглядеть так:
foreach (Control c in Concat(tb_Invoices.Controls, tb_Statements.Controls))
{
//do something
}
простой, дешевый и выразительный!
EDIT: если ваша коллекция не реализует IEnumerable<T>
, но только IEnumerable
, вы можете добавить перегрузку, которая примет последнее. Все остается по-прежнему, за исключением того, что T
изменения object
во вложенном цикле.