I need to loop through all the controls in my asp.net webpage and do something to the control. In one instance I'm making a giant string out of the page and emailing it to myself, and in another case I'm saving everything to a cookie.
The problem is masterpages and items with collections of controls inside them. I want to be able to pass in a Page to the method, then have that method be generic enough to loop through all controls in the inner-most content page and work with them. I've tried doing this with recursion, but my recursion is incomplete.
I want to pass a Page object into a method, and have that method loop through all controls in the innermost content page. How can I achieve this?
    private static String controlToString(Control control)
{
    StringBuilder result = new StringBuilder();
    String controlID = String.Empty;
    Type type = null;
    foreach (Control c in control.Controls)
    {
        try
        {
            controlID = c.ID.ToString();
            if (c is IEditableTextControl)
            {
                result.Append(controlID + ": " + ((IEditableTextControl)c).Text);
                result.Append("<br />");
            }
            else if (c is ICheckBoxControl)
            {
                result.Append(controlID + ": " + ((ICheckBoxControl)c).Checked);
                result.Append("<br />");
            }
            else if (c is ListControl)
            {
                result.Append(controlID + ": " + ((ListControl)c).SelectedValue);
                result.Append("<br />");
            }
            else if (c.HasControls())
            {
                result.Append(controlToString(c));
            }
            //result.Append("<br />");
        }
        catch (Exception e)
        {
        }
    }
    return result.ToString();
}
Without Try/catch
Object reference not set to an instance of an object.
On line controlID = .....
I rather like David Finleys linq approach to FindControl http://weblogs.asp.net/dfindley/archive/2007/06/29/linq-the-uber-findcontrol.aspx
public static class PageExtensions
{
    public static IEnumerable<Control> All(this ControlCollection controls)
    {
        foreach (Control control in controls)
        {
            foreach (Control grandChild in control.Controls.All())
                yield return grandChild;
            yield return control;
        }
    }
}
Usage:
// get the first empty textbox
TextBox firstEmpty = accountDetails.Controls
    .All()
    .OfType<TextBox>()
    .Where(tb => tb.Text.Trim().Length == 0)
    .FirstOrDefault();
// and focus it
if (firstEmpty != null)
    firstEmpty.Focus();
                        Your original method will not work if you start from the root element of your document: something like page.Controls as you will only loop through the first level of controls, but remember a control can be composite. So you need recursion to pull that off.
        public void FindTheControls(List<Control> foundSofar, Control parent) 
        {
            foreach(var c in parent.Controls) 
            {
                  if(c is IControl) //Or whatever that is you checking for 
                  {
                      foundSofar.Add(c);
                      if(c.Controls.Count > 0) 
                      {
                            this.FindTheControls(foundSofar, c);
                      }
                  }
            }  
        }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With