C# 获取页面上特定类型的所有Web控件

C# 获取页面上特定类型的所有Web控件,c#,asp.net,webforms,C#,Asp.net,Webforms,我一直在思考如何在一个页面上获取所有控件,然后在此相关问题中对它们执行任务: 我需要的代码,可以扫描页面,获得所有的下拉列表控件,并返回他们在一个列表中 我目前必须编辑每个控件,我希望能够动态循环每个控件以执行我的任务。var dropDownLists=new List(); var dropDownLists = new List<DropDownList>(); foreach (var control in this.Controls)

我一直在思考如何在一个页面上获取所有控件,然后在此相关问题中对它们执行任务:

我需要的代码,可以扫描页面,获得所有的下拉列表控件,并返回他们在一个列表中

我目前必须编辑每个控件,我希望能够动态循环每个控件以执行我的任务。

var dropDownLists=new List();
        var dropDownLists = new List<DropDownList>();
        foreach (var control in this.Controls)
        {
            if (control is DropDownList)
            {
                dropDownLists.Add( (DropDownList)control );
            }
        }
foreach(此.Controls中的var控件) { 如果(控件为下拉列表) { 添加((DropDownList)控件); } }
在页面上的控件之间循环并不困难-您只需在每个控件中查找更多控件即可

你可以这样做

foreach(var control in Page)
{
    if(control is DropDownList)
    {
        //Do whatever
    }
    else
    {
        //Call this function again to search for controls within this control
    }
}

您可以使用递归逻辑获取所有控件,如下所示:

private void PopulateSelectList(Control parentCtrl, List<DropDownList> selectList)
{
    foreach (Control ctrl in parentCtrl.Controls)
    {
        if (ctrl is DropDownList)
        {
            selectList.Add(((DropDownList)ctrl);
            continue;
        }
        FindAllControls(ctrl, selectList);
    }
}
private void PopulateSelectList(Control parentCtrl,List selectList)
{
foreach(parentCtrl.Controls中的控件ctrl)
{
如果(ctrl为下拉列表)
{
选择列表。添加(((下拉列表)ctrl);
继续;
}
FindAllControl(ctrl、selectList);
}
}
检查

基本上,我们的想法是使用以下方法包装遍历控件集合的递归:

private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection)
where T : Control
{
    foreach (Control control in controlCollection)
    {
        //if (control.GetType() == typeof(T))
        if (control is T) // This is cleaner
            resultCollection.Add((T)control);

        if (control.HasControls())
            GetControlList(control.Controls, resultCollection);
    }
}
由于使用了
yield
关键字,并且由于Linq足够聪明,可以推迟枚举的执行,因此可以调用(例如):

var allDropDowns=this.Page.finddescents();
var firstDropDownWithCustomClass=allDropDowns.First(
ddl=>ddl.CssClass==“自定义类”
);
一旦满足
First
方法中的谓词,枚举将停止。将不会遍历整个控件树。

foreach(DropDownList dr in this.Page.Form.Controls.OfType())
foreach (DropDownList dr in this.Page.Form.Controls.OfType<DropDownList>())
{

}
{ }
有一个问题,虽然我发现Steve B的答案很有用,但我想要一个扩展方法,所以重新考虑了它:

    public static IEnumerable<T> GetControlList<T>(this ControlCollection controlCollection) where T : Control
    {
        foreach (Control control in controlCollection)
        {
            if (control is T)
            {
                yield return (T)control;
            }

            if (control.HasControls())
            {
                foreach (T childControl in control.Controls.GetControlList<T>())
                {
                    yield return childControl;
                }
            }
        }
    }
公共静态IEnumerable GetControlList(此ControlCollection ControlCollection),其中T:Control
{
foreach(controlCollection中的控件)
{
如果(控制为T)
{
收益率(T)控制;
}
if(control.HasControls())
{
foreach(control.Controls.GetControlList()中的T childControl)
{
收益控制;
}
}
}
}

这里是一个递归版本,它返回请求类型的控件集合,而不是使用另一个参数:

using System.Collections.Generic;
using System.Web.UI;
// ...
public static List<T> GetControls<T>(ControlCollection Controls)
where T : Control {
  List<T> results = new List<T>();
  foreach (Control c in Controls) {
    if (c is T) results.Add((T)c);
    if (c.HasControls()) results.AddRange(GetControls<T>(c.Controls));
  }
  return results;
}
使用System.Collections.Generic;
使用System.Web.UI;
// ...
公共静态列表GetControls(ControlCollection控件)
其中T:控制{
列表结果=新列表();
foreach(控件中的控件c){
如果(c是T)结果,则添加((T)c);
if(c.HasControls())results.AddRange(GetControls(c.Controls));
}
返回结果;
}

插入到类中(静态可选)。

如果使用system.web.ui中的表单组件,则此操作有效 然而,当您从system.web.mvc使用它们时,这显然不起作用,因此我提出了以下解决方法

for (Int32 idx = 0; idx < formCollection.Count; idx += 1)
                    {
                    String Name = formCollection.Keys[idx];
                    String value = formCollection[idx];

                    if (Name.Substring(0, 3).ToLower() == "chk")

                        {
                        Response.Write(Name + " is a checkbox <br/>");
                        }
                    else if (Name.Substring(0, 5).ToLower() == "txtar")
                        {
                        Response.Write(Name + " is a text area <br/>");
                        }
                    else if (Name.Substring(0, 2).ToLower() == "rd")
                        {
                        Response.Write(Name + " is a RadioButton <br/>");
                        }

                    }
for(Int32 idx=0;idx”;
}
else if(Name.Substring(0,5).ToLower()=“txtar”)
{
Response.Write(Name+“是一个文本区域
”); } else if(Name.Substring(0,2).ToLower()=“rd”) { 响应。写入(Name+“是单选按钮
”; } }

这对我来说很有用,但是我发现单选按钮if not selected为null,因此不返回任何可以的内容如果为null,我不必向数据库写入任何内容

我非常确定您需要递归。这就是其他的功能…//再次调用此函数以搜索此控件中的控件…这需要一些东西ng recursive…最全面的答案,它就像一个魅力欢呼的伙伴。关于msdn的好文章很好。我喜欢它。很好,我不再需要使用yield关键字,这使得递归函数始终运行,即使我声明Visual Studio要跳过它。如果您添加实际使用此扩展的示例会更好n方法,例如,
foreach(Page.GetAllControls()中的var-tbox){tbox.Text=box.Text.Trim();}
这是对原始问题的直接回答。@Fernando68:你应该问一个特定的问题,所以…我展示的代码来自一个更大的项目…我不能发布它。是的!你需要迭代每个控件集合-递归。但是我认为这些扩展方法非常有用,因为它们使你的代码更紧凑-更我看不出这个答案对于包含其他控件的控件的任何页面都能正确工作。正如@JamesJohnson所指出的,要正确找到所有DropDownList,您需要递归搜索所有控件(正如许多其他答案所做的那样),而不仅仅是顶级控件。在我的实现中,此答案并没有返回我页面上的所有控件。我是否遗漏了任何内容?我在“this”上看到intelli sense错误,表示“Type expected”。我只是将其添加到app_code文件夹中的类中。
foreach (DropDownList dr in this.Page.Form.Controls.OfType<DropDownList>())
{

}
    public static IEnumerable<T> GetControlList<T>(this ControlCollection controlCollection) where T : Control
    {
        foreach (Control control in controlCollection)
        {
            if (control is T)
            {
                yield return (T)control;
            }

            if (control.HasControls())
            {
                foreach (T childControl in control.Controls.GetControlList<T>())
                {
                    yield return childControl;
                }
            }
        }
    }
using System.Collections.Generic;
using System.Web.UI;
// ...
public static List<T> GetControls<T>(ControlCollection Controls)
where T : Control {
  List<T> results = new List<T>();
  foreach (Control c in Controls) {
    if (c is T) results.Add((T)c);
    if (c.HasControls()) results.AddRange(GetControls<T>(c.Controls));
  }
  return results;
}
for (Int32 idx = 0; idx < formCollection.Count; idx += 1)
                    {
                    String Name = formCollection.Keys[idx];
                    String value = formCollection[idx];

                    if (Name.Substring(0, 3).ToLower() == "chk")

                        {
                        Response.Write(Name + " is a checkbox <br/>");
                        }
                    else if (Name.Substring(0, 5).ToLower() == "txtar")
                        {
                        Response.Write(Name + " is a text area <br/>");
                        }
                    else if (Name.Substring(0, 2).ToLower() == "rd")
                        {
                        Response.Write(Name + " is a RadioButton <br/>");
                        }

                    }