获取页面上特定类型的所有 Web 控件 [英] Get All Web Controls of a Specific Type on a Page

查看:42
本文介绍了获取页面上特定类型的所有 Web 控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been pondering how I can get all controls on a page and then perform a task on them in this related question:

如何以编程方式搜索 C# DropDownList

我需要可以扫描页面、获取所有 DropDownList 控件并将它们返回到列表中的代码.

I need code that can scan the page, get all DropDownList Controls and return them in a list.

我目前必须编辑每个单独的控件,我宁愿能够动态循环每个控件来执行我的任务.

I'm currently having to edit each individual control, I would rather be able to dynamically loop over each control to preform my task.

推荐答案

检查 我之前的 SO 答案.

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

Basically, the idea is to wrap the recursion of iterating through the controls collection using :

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

并使用它:

List<DropDownList> allControls = new List<DropDownList>();
GetControlList<DropDownList>(Page.Controls, allControls )
foreach (var childControl in allControls )
{
//     call for all controls of the page
}

[Edited 11/26/2013]:这是实现这一目标的更优雅的方式.我写了两个扩展方法,可以双向遍历控制树.这些方法是用更 Linq 的方式编写的,因为它产生了一个可枚举的:

: here is a more elegant way to reach this goal. I wrote two extensions methods that can walk the control tree in both directions. The methods are written in a more Linq way as it produces an enumerable:

/// <summary>
/// Provide utilities methods related to <see cref="Control"/> objects
/// </summary>
public static class ControlUtilities
{
    /// <summary>
    /// Find the first ancestor of the selected control in the control tree
    /// </summary>
    /// <typeparam name="TControl">Type of the ancestor to look for</typeparam>
    /// <param name="control">The control to look for its ancestors</param>
    /// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns>
    public static TControl FindAncestor<TControl>(this Control control) where TControl : Control
    {
        if (control == null) throw new ArgumentNullException("control");

        Control parent = control;
        do
        {
            parent = parent.Parent;
            var candidate = parent as TControl;
            if (candidate != null)
            {
                return candidate;
            }
        } while (parent != null);
        return null;
    }

    /// <summary>
    /// Finds all descendants of a certain type of the specified control.
    /// </summary>
    /// <typeparam name="TControl">The type of descendant controls to look for.</typeparam>
    /// <param name="parent">The parent control where to look into.</param>
    /// <returns>All corresponding descendants</returns>
    public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control
    {
        if (parent == null) throw new ArgumentNullException("control");

        if (parent.HasControls())
        {
            foreach (Control childControl in parent.Controls)
            {
                var candidate = childControl as TControl;
                if (candidate != null) yield return candidate;

                foreach (var nextLevel in FindDescendants<TControl>(childControl))
                {
                    yield return nextLevel;
                }
            }
        }
    }
}

感谢this关键字,这些方法都是扩展方法,可以简化代码.

Thanks to the this keyword, these methods are extensions methods and can simplify the code.

例如,要查找页面中的所有DropDownList,只需调用:

For example, to find all DropDownList in the page, you can simply call:

var allDropDowns = this.Page.FindControl<DropDownList>();

因为使用了 yield 关键字,并且因为 Linq 足够聪明,可以推迟枚举的执行,您可以调用(例如):

Because of the use of the yield keyword, and because Linq is smart enough to defer execution of the enumeration, you can call (for example):

var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
    ddl=>ddl.CssClass == "customclass"
    );

只要满足 First 方法中的谓词,枚举就会停止.不会遍历整个控制树.

The enumeration will stop as soon as the predicate in the First method is satisfied. The whole control tree won't be walked.

这篇关于获取页面上特定类型的所有 Web 控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆