Loop through all controls on asp.net webpage
Asked Answered
P

7

6

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 = .....

Parkman answered 23/11, 2010 at 19:16 Comment(3)
What is the error that you are getting?Whiney
No error, my string simply doesn't have entries representing every control.Parkman
The reason you're not getting an error is because you have a try/catch block hiding it. Remove that and see what happens.Boresome
K
8

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);
                      }
                  }


            }  

        }
Korikorie answered 23/11, 2010 at 20:26 Comment(5)
Ok, so can I pass a Page object into this? What can I pass into this?Parkman
Also, what is the advantage of using var c over Control c?Parkman
@Parkman Syntactic sugar, they are the sameIndescribable
So, if I'm looking for TextBoxes, it will check if the current control is a textbox, add it, and then check if that textbox has child controls? What if I'm looking for textboxes and the current control is a panel in which my textbox resides? This code doesn't seem to account for that.Roofdeck
To my understanding, textboxes, labels, checkboxes etc are not containers so a textbox cannot contain a textbox so if you are looking for text boxes, it will find them even in a child panel.Brandabrandais
P
27

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();
Publication answered 11/1, 2012 at 23:34 Comment(0)
K
8

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);
                      }
                  }


            }  

        }
Korikorie answered 23/11, 2010 at 20:26 Comment(5)
Ok, so can I pass a Page object into this? What can I pass into this?Parkman
Also, what is the advantage of using var c over Control c?Parkman
@Parkman Syntactic sugar, they are the sameIndescribable
So, if I'm looking for TextBoxes, it will check if the current control is a textbox, add it, and then check if that textbox has child controls? What if I'm looking for textboxes and the current control is a panel in which my textbox resides? This code doesn't seem to account for that.Roofdeck
To my understanding, textboxes, labels, checkboxes etc are not containers so a textbox cannot contain a textbox so if you are looking for text boxes, it will find them even in a child panel.Brandabrandais
E
3
foreach (Control ctlMaster in Page.Controls)
{
    if (ctlMaster is MasterPage)
    {
        foreach (Control ctlForm in ctlMaster.Controls)
        {
            if (ctlForm is HtmlForm)
            {
                foreach (Control ctlContent in ctlForm.Controls)
                {
                    if (ctlContent is ContentPlaceHolder)
                    {
                        foreach (Control ctlChild in ctlContent.Controls)
                        {
                            //Do something!
                        }
                    }
                }
            }
        }
    }
}

This should do it. Though you might need to do some checking to make sure you're actually dealing with the correct ContentPlaceHolder if there's more than one.

Epicurean answered 13/4, 2011 at 0:0 Comment(0)
L
0
sub getcontrols(byref c as control, byref allControls as list(of control)
if c isnot nothing
allcontrols.add(c)
if c.controls.count>0 then
for each ctrl as control in c.controls
getcontrols(ctrl,allcontrols)
next
end if
Lamphere answered 23/11, 2010 at 20:7 Comment(1)
I'm not sure this is relevant to the ASP.net question.Lh
D
0

This worked for me ..

Just make sure you ID all your controls starting with the prefixes shown below. ie: <asp:TextBox ID="TextBoxEmail"...> for example. Otherwise the parser will not detect your control. If someone has a better way of parsing without knowing / hard-coding the ID of the controls, that would be even sweeter.

protected String GetControls(Control control)
{
    //Get text from form elements
    String text = "";
    foreach (Control ctrl in control.Controls)
    {
        if (ctrl.ClientID.Contains("TextBox"))
        {
            TextBox tb = (TextBox)ctrl;
            text += tb.ID.Replace("TextBox", "") + ": " + tb.Text + "<br />";
        }
        if (ctrl.ClientID.Contains("RadioButtonList"))
        {
            RadioButtonList rbl = (RadioButtonList)ctrl;
            text += rbl.ID.Replace("RadioButtonList", "") + ": " + rbl.SelectedItem.Text + "<br />";
        }
        if (ctrl.ClientID.Contains("DropDownList"))
        {
            DropDownList ddl = (DropDownList)ctrl;
            text += ddl.ID.Replace("DropDownList", "") + ": " + ddl.SelectedItem.Text + "<br />";
        }

        if (ctrl.ClientID.Contains("CheckBox"))
        {
            CheckBox cb1 = (CheckBox)ctrl;
            text += cb1.ID.Replace("CheckBox", "") + ": " + cb1.Text + "<br />";
        }

        if (ctrl.HasControls())
            text += GetControls(ctrl);
    }

    return text;
}

And to call it, passing Page object ...

String log;
foreach (Control ctrl in Page.Controls)
    log += GetControls(ctrl);
Drooff answered 1/9, 2015 at 2:59 Comment(0)
C
0

Please find the below code. This should help you with all the controls you need. You should be able to use Web Page Controls, as well as ASP.NET Controls.

public partial class Default : System.Web.UI.Page
{

List<Control> lstControl = new List<Control>();

protected void Page_Load(object sender, EventArgs e)
{

}

private List<Label> getLabels() // Add all Lables to a list
{
    List<Label> lLabels = new List<Label>();

    foreach (Control oControl in Page.Controls)
    {
        GetAllControlsInWebPage(oControl);
    }

    foreach (Control oControl in lstControl)
    {
        if (oControl.GetType() == typeof(Label))
        {
            lLabels.Add((Label)oControl);
        }
    }
    return lLabels;
}

protected void GetAllControlsInWebPage(Control oControl)
{
    foreach (Control childControl in oControl.Controls)
    {
        lstControl.Add(childControl); //lstControl - Global variable
        if (childControl.HasControls())
            GetAllControlsInWebPage(childControl);
    }
}

}
Contemplative answered 16/6, 2016 at 10:12 Comment(0)
E
-1

Even though this question has been discussed for more than 9 years, here I leave the code that worked for me based on @Jagadheesh Venkatesan's code.

private List<Control> getControls()
{
    List<Control> lControls = new List<Control>();
    foreach (Control oControl in Page.Controls)
        foreach (Control childControl1 in oControl.Controls)
            foreach (Control childControl2 in childControl1.Controls)
                foreach (Control childControl3 in childControl2.Controls)
                    if (childControl3.GetType().ToString().Contains("System.Web.UI.WebControls"))
                        lControls.Add(childControl3);
    return lControls;
}
Eimile answered 29/1, 2020 at 22:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.