Member 11709930 Ответов: 2

Перебора элементов datagridview на элемент управления TabControl


У меня есть TabControl с 6 страницами. На каждой странице есть GroupBox с DataGridView на нем.
Мне нужно перебрать все 6 представлений DataGridViews как часть процедуры проверки ячеек.

Что я уже пробовал:

Я создал этот код, чтобы найти все DGV, чтобы я мог перебирать их, но он, похоже, вообще не находит никаких DGV.
foreach (DataGridView dgv in this.tabControl1.Controls.OfType<DataGridView>())
{
}
Также пробовать
foreach (DataGridView dgv in this.Controls.OfType<DataGridView>())
что тоже неудача.

Я могу найти DGV с помощью этого кода, детализирующего отдельные коллекции элементов управления, но это кажется смехотворно сложным. Конечно, есть более простой способ?
foreach (Control c in this.tabControl1.Controls)
       {
           if (c is TabPage)
           {
               foreach (Control d in c.Controls)
               {
                   if (d is GroupBox)
                   {
                       foreach (Control e in d.Controls)
                       {
                           if (e is DataGridView)
                           {
                               DataGridView dgv = (DataGridView)e;
                                // process the DGVs
                           }
                       }
                   }
               }
           }
       }



Что я упускаю?

2 Ответов

Рейтинг:
19

BillWoodruff

Вы должны детализировать; я бы использовал Linq:

private List<DataGridView> DGViews;

private void Form1_Load(object sender, EventArgs e)
{
    DGViews = tabControl1.TabPages
        .Cast<TabPage>()
        .SelectMany((TabPage tab) => tab.Controls.OfType<DataGridView>())
        .ToList();
}
Поскольку каждый вызов 'OfType возвращает IEnumerable, использование 'SelectMany делает правильную вещь для перечисления этих промежуточных результатов.

Вы можете использовать " элементы управления.Найти которые при желании смогут повторить, но это поиски на ключ/имя свойства элемента управления: вы можете"Т использовать его, чтобы получить все элементы одного типа.


Richard Deeming

Вам, вероятно, понадобится еще один уровень SelectMany там, чтобы отчитаться за то, что GroupBox. :)

BillWoodruff

Действительно ! Если бы GroupBox был единственным элементом управления на вкладке с DGV внутри него, это было бы тривиально; если бы структура была более сложной, то потребовалась бы рекурсия.

Maciej Los

5ed!

Рейтинг:
10

Richard Deeming

Вот вспомогательный метод, который я нахожу полезным в такой ситуации:

public static class TreeExtensions
{
    public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
    {
        if (source is null) throw new ArgumentNullException(nameof(source));
        if (getChildren is null) throw new ArgumentNullException(nameof(getChildren));
        return Iterator();
        
        IEnumerable<T> Iterator()
        {
            var stack = new Stack<IEnumerator<T>>();
            try
            {
                stack.Push(source.GetEnumerator());
                while (stack.Count != 0)
                {
                    var iter = stack.Peek();
                    if (iter.MoveNext())
                    {
                        var current = iter.Current;
                        yield return current;
                        
                        var children = getChildren(current);
                        if (children != null) stack.Push(children.GetEnumerator());
                    }
                    else
                    {
                        iter.Dispose();
                        stack.Pop();
                    }
                }
            }
            finally
            {
                while (stack.Count != 0)
                {
                    stack.Pop().Dispose();
                }
            }
        }
    }
}

Теперь вы можете искать все дерево элементов управления с помощью LINQ:
IEnumerable<DataGridView> dataGrids = this.Controls.Cast<Control>()
    .SelectRecursive(c => c.HasChildren ? c.Controls.Cast<Control>() : null)
    .OfType<DataGridView>();


Maciej Los

5ed!

BillWoodruff

+5 учитель говорит: Я учусь :) Я использую рекурсию на основе стека с тех пор, как Эрик Липперт показал мне, как много лет назад; что мне действительно нравится, так это то, как вы сделали ее "обобщенной" с помощью дженериков и методов расширения.