循环访问 asp.net 网页上的所有控件

Posted

技术标签:

【中文标题】循环访问 asp.net 网页上的所有控件【英文标题】:Loop through all controls on asp.net webpage 【发布时间】:2011-05-14 16:14:03 【问题描述】:

我需要遍历我的 asp.net 网页中的所有控件并对控件执行一些操作。在一种情况下,我从页面中制作了一个巨大的字符串并将其通过电子邮件发送给自己,在另一种情况下,我将所有内容保存到 cookie 中。

问题在于母版页和项目中包含控件集合。我希望能够将 Page 传递给该方法,然后让该方法足够通用,以循环遍历最内层内容页面中的所有控件并使用它们。我试过用递归来做这件事,但我的递归是不完整的。

我想将一个 Page 对象传递给一个方法,并让该方法循环遍历最内层内容页面中的所有控件。我怎样才能做到这一点?

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

没有尝试/捕获

对象引用未设置为对象的实例。

在线 controlID = .....

【问题讨论】:

您遇到的错误是什么? 没有错误,我的字符串根本没有代表每个控件的条目。 你没有收到错误的原因是因为你有一个 try/catch 块隐藏它。删除它,看看会发生什么。 【参考方案1】:

我更喜欢 David Finley 对 FindControl 的 linq 方法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;
        
    

用法:

// 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();

【讨论】:

【参考方案2】:

如果您从文档的根元素开始,您的原始方法将不起作用:类似于 page.Controls,因为您只会循环第一级控件,但请记住,控件可以是复合的。所以你需要递归来实现它。

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


              

        

【讨论】:

好的,我可以将 Page 对象传递给它吗?我可以传递什么? 另外,使用 var c 相对于 Control c 有什么优势? @MAW74656 语法糖,它们是一样的 所以,如果我在寻找TextBoxes,它会检查当前控件是否是一个文本框,添加它,然后检查该文本框是否有子控件?如果我正在寻找文本框并且当前控件是我的文本框所在的面板怎么办?这段代码似乎没有考虑到这一点。 据我了解,文本框、标签、复选框等不是容器,因此文本框不能包含文本框,因此如果您要查找文本框,它甚至可以在子面板中找到它们。【参考方案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!
                        
                    
                
            
        
    

应该这样做。尽管您可能需要进行一些检查以确保您实际上正在处理正确的 ContentPlaceHolder(如果有多个)。

【讨论】:

【参考方案4】:
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

【讨论】:

我不确定这是否与 ASP.net 问题有关。【参考方案5】:

这对我有用..

只需确保所有控件都以如下所示的前缀开头。即:&lt;asp:TextBox ID="TextBoxEmail"...&gt; 例如。否则解析器将不会检测到您的控件。如果有人在不知道/硬编码控件 ID 的情况下有更好的解析方式,那就更棒了。

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;

然后调用它,传递 Page 对象 ...

String log;
foreach (Control ctrl in Page.Controls)
    log += GetControls(ctrl);

【讨论】:

【参考方案6】:

请找到以下代码。这应该可以帮助您获得所需的所有控件。您应该能够使用网页控件以及 ASP.NET 控件。

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



【讨论】:

【参考方案7】:

尽管这个问题已经讨论了 9 年多,但我还是留下了基于 @Jagadheesh Venkatesan 的代码为我工作的代码。

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;

【讨论】:

以上是关于循环访问 asp.net 网页上的所有控件的主要内容,如果未能解决你的问题,请参考以下文章

使用 asp.net 控件操作数据的一些数据访问选项是啥?

从 asp.net 扫描图像

简述asp.net中控件的种类及特点

动态创建的 asp.net 控件在回发后消失

在 ASP.NET 控件上使用 ajax/jQuery 表单验证

ASP.NET 访问 DataList 控件内的 Web 控件