Click here to Skip to main content
15,889,281 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
I have a TabControl with 6 pages. Each page has a GroupBox with a DataGridView on it.
I need to loop through all 6 DataGridViews as part of a cell validation routine.

What I have tried:

I've created this code to find all the DGV's so I can loop through them but it does not seem to find any DGV's at all.
foreach (DataGridView dgv in this.tabControl1.Controls.OfType<DataGridView>())
{
}
Also tried
foreach (DataGridView dgv in this.Controls.OfType<DataGridView>())
which is also a failure.

I can find the DGV's with this code drilling down through the individual control collections but it seems ridiculously complicated. Surely there is a simpler way?
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
                           }
                       }
                   }
               }
           }
       }



What am I missing?
Posted
Updated 4-Apr-19 6:38am
v5

You gotta drill-down; I'd use 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();
}
Since every call to 'OfType returns an IEnumerable, the use of 'SelectMany does the right thing to enumerate those intermediate results.

You can use 'Controls.Find which can optionally recurse, but it searches on the key/name property of a Control: you can''t use that to get all Controls of the same Type.
 
Share this answer
 
Comments
Richard Deeming 4-Apr-19 12:23pm    
You'll probably need another level of SelectMany in there to account for the GroupBox. :)
BillWoodruff 4-Apr-19 19:55pm    
Indeed ! If the GroupBox were the only Control on the TabPage with a DGV inside it, that's trivial; if more complex structure, recursion would be required.
Maciej Los 4-Apr-19 12:50pm    
5ed!
Here's a helper method I find useful in this sort of situation:
C#
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();
                }
            }
        }
    }
}

With that in place, you can now search your entire control tree using LINQ:
C#
IEnumerable<DataGridView> dataGrids = this.Controls.Cast<Control>()
    .SelectRecursive(c => c.HasChildren ? c.Controls.Cast<Control>() : null)
    .OfType<DataGridView>();
 
Share this answer
 
Comments
Maciej Los 4-Apr-19 12:50pm    
5ed!
BillWoodruff 4-Apr-19 19:54pm    
+5 The master speaks: I learn :) I've been using stack based recursion ever since Eric Lippert showed me how many years ago; what I really like is the way you have made it "generalized" with generics and Extension Methods.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900