In my app I have some functions that loop over all the components in a form to establish some properties like the following ones:
Function used to set all the textbox in a form to readonly when we are just viewing data:
public void SetReadOnly(Control.ControlCollection controls, bool readOnly)
{
    foreach(var panel in controls.OfType<Panel>())
    {
        SetReadOnly(panel.Controls, readOnly);
    }
    foreach(var tabpageview in controls.OfType<TabPageView>())
    {
        foreach(var tabpageviewpage in tabpage.Controls)
        {
            SetReadOnly(tagpageviewpage.Controls, readOnly);
        }
    }
    foreach(var textbox in controls.OfType<TextBox>())
    {
        textbox.ReadOnly = readOnly;
    }
}
Function used to clean the content of all the textboxes after data has been inserted in the database:
public void CleanTextBox(Control.ControlCollection controls)
{
    foreach(var panel in controls.OfType<Panel>())
    {
        CleanTextBox(panel.Controls);
    }
    foreach(var tabpageview in controls.OfType<TabPageView>())
    {
        foreach(var tabpageviewpage in tabpage.Controls)
        {
            CleanTextBox(tagpageviewpage.Controls);
        }
    }
    foreach(var textbox in controls.OfType<TextBox>())
    {
        textbox.Text = "";
    }
}
Function that receives a list of fields and paint the labels with that name to red to remark that is required:
public void SetRequired(Control.ControlCollection controls, List<string> requiredFields)
{
    foreach(var panel in controls.OfType<Panel>())
    {
        SetRequired(panel.Controls, requiredFields);
    }
    foreach(var tabpageview in controls.OfType<TabPageView>())
    {
        foreach(var tabpageviewpage in tabpage.Controls)
        {
            SetRequired(tagpageviewpage.Controls, requiredFields);
        }
    }
    foreach(var field in requiredFields)
    {
        FindLabelByName(field).Foreground(Color.Red);
    }
}    
As you can see all those function has something in common where they receive a collection of controls and loop over them. If it is a panel, a tabpageview, or another component with children, then it loops again until it find its textboxes and do some action.
Is it possible to make one function that receives another function as a parameter so if I start using groupboxes I can just put it in one function instead of having to put it in all the functions? Something like this.
public void LoopComponents(Control.ControlCollection controls, xxx function)
{
    foreach(var panel in controls.OfType<Panel>())
    {
        LoopComponents(panel.controls, function);
    }
    foreach(var tabpageview in controls.OfType<TabPageView>())
    {
        foreach(var tabpageviewpage in tabpageview.Controls)
        {
            LoopComponents(tabpageviewpage.Controls, function);
        }
    }
    function();
}
public void SetReadOnly(Control.ControlCollection controls, bool readOnly)
{
    foreach(var textbox in controls.OfType<TextBox>())
    {
        textbox.ReadOnly = readOnly;
    }
}
public void CleanTextBox(Control.ControlCollection controls)
{
    foreach(var textbox in controls.OfType<TextBox>())
    {
        textbox.Text = "";
    }
}
public void SetRequired(Control.ControlCollection controls, List<string> requiredFields)
{
    foreach(var field in requiredFields)
    {
        FindLabelByName(field).Foreground(Color.Red);
    }
}   
public void Test()
{
    LoopComponents(Controls, SetReadOnly(Controls, true));
    LoopComponents(Controls, CleanTextBox(Controls));
    LoopComponents(Controls, SetRequired(Controls, requiredFieldsList));
}
Currently I'm using C# 4.0, but if it's possible in a later version it doesn't matter, just curious to know if it's possible. Thanks
 
    