Search code examples
c#winformsdatagridviewtabcontroltabpage

How to get content of sub-controls in WinForm?


I have WinForm, which have many controls (tabcontrol, tabpage, datagridview,...etc). I want to get data in datagridview. The structure of design is like this (TabControl will have many TabPages, each TabPage will have one TabControl, each TabControl will have many TabPages, each TabPage will have one DataGridView).

TabControlX
+TabPage
++TabControl
+++TabPage
++++DataGridView
+++TabPage
++++DataGridView
+TabPage
++TabControl
+++TabPage
++++DataGridView
+++TabPage
++++DataGridView

So, I want to get data each DataGridView. I'm not sure if the stuff is correct or bad.

            foreach (TabPage tbp in tabControl_X.TabPages)
            {
                foreach (Control item in tbp.Controls)
                {
                    foreach (TabPage sub_tab in item.Controls)
                    {
                        foreach (Control dgv in sub_tab.Controls)
                        {
                            //how to get data dgv?
                        }
                    }
                }
            }

Solution

  • To iterate the control hierarchy of the Form, make an iterator method similar to this:

    public partial class MainForm : Form
    {
        IEnumerable<Control> IterateControls(Control.ControlCollection controls)
        {
            foreach (Control control in controls) 
            {
                yield return control;
                foreach (Control child in IterateControls(control.Controls))
                { 
                    yield return child;
                }
            }
        }
    }
    

    First, demonstrate the iterator by listing ALL the controls:

    // Iterate all names
    Debug.WriteLine("ALL CONTROLS");
    foreach (var control in IterateControls(Controls))
    {
        Debug.WriteLine(
            string.IsNullOrWhiteSpace(control.Name) ?
                $"Unnamed {control.GetType().Name}"  :
                control.Name);
    }
    

    list all controls

    An additional extension indents the output by depth see Repo.


    Your question is how about getting just the DataGridView controls, so specify OfType()

    
    // Iterate DataGridView only
    Debug.WriteLine("\nDATA GRID VIEW CONTROLS");
    foreach (var control in IterateControls(Controls).OfType<DataGridView>())
    {
        Debug.WriteLine(control.Name);
    }
    

    data grid view controls