在ASP.NET中找到控件的更好方法

san*_*ngh 46 asp.net findcontrol

我有一个复杂的asp.net表单,在一个表单中甚至有50到60个字段Multiview,在MultiView中我有一个GridView,而在GridView中我有几个CheckBoxes.

目前我正在使用该FindControl()方法的链接并检索子ID.

现在,我的问题是,是否有任何其他方法/解决方案可以在ASP.NET中找到嵌套控件.

jim*_*mig 72

如果你正在寻找一种特定类型的控件,你可以使用像这样的递归循环 - http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol-recursive-with -generics.aspx

这是我做的一个例子,它返回给定类型的所有控件

/// <summary>
/// Finds all controls of type T stores them in FoundControls
/// </summary>
/// <typeparam name="T"></typeparam>
private class ControlFinder<T> where T : Control 
{
    private readonly List<T> _foundControls = new List<T>();
    public IEnumerable<T> FoundControls
    {
        get { return _foundControls; }
    }    

    public void FindChildControlsRecursive(Control control)
    {
        foreach (Control childControl in control.Controls)
        {
            if (childControl.GetType() == typeof(T))
            {
                _foundControls.Add((T)childControl);
            }
            else
            {
                FindChildControlsRecursive(childControl);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 警告:给定的解决方案对我来说不起作用,因为它从不指责相同的类型._I think_如果childControl是用户控件,GetType()是不够的.**childControl.GetType().BaseType**对我有用.希望它能帮助别人.neverthless,谢谢@Jimmy的解决方案:) (4认同)
  • 很棒的代码,非常感谢。我试图自己写这种东西,结果得到了一个丑陋的意大利面球。这好多了。@MassStrike,如果您使用最通用的类​​型,则您的代码更具可移植性。这是一个很好的习惯,这就是为什么你到处都能看到它。 (2认同)

Dav*_*rke 18

像往常一样晚.如果有人仍然对此感兴趣,那么有许多相关的SO 问题答案.我的版本的递归扩展方法解决了这个问题:

public static IEnumerable<T> FindControlsOfType<T>(this Control parent)
                                                        where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is T)
        {
            yield return (T)child;
        }
        else if (child.Controls.Count > 0)
        {
            foreach (T grandChild in child.FindControlsOfType<T>())
            {
                yield return grandChild;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请务必注意,此方法必须位于静态类中,因为它会为Control类型创建扩展方法.否则,您将收到此编译错误:"必须在非泛型静态类中定义扩展方法." (3认同)

Ond*_*dar 9

所有突出显示的解决方案都使用递归(性能代价高昂).这是没有递归的更清洁的方式:

public T GetControlByType<T>(Control root, Func<T, bool> predicate = null) where T : Control 
{
    if (root == null) {
        throw new ArgumentNullException("root");
    }

    var stack = new Stack<Control>(new Control[] { root });

    while (stack.Count > 0) {
        var control = stack.Pop();
        T match = control as T;

        if (match != null && (predicate == null || predicate(match))) {
            return match;
        }

        foreach (Control childControl in control.Controls) {
           stack.Push(childControl);
        }
    }

    return default(T);
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来不错,但如何使用?示例会很好. (3认同)

Tim*_*ter 6

FindControl不会递归地在嵌套控件中搜索.它只找到NamigContainer是您正在调用FindControl的控件.

这是ASP.Net默认情况下不会递归查看嵌套控件的原因:

  • 性能
  • 避免错误
  • 可重用性

考虑到您希望将其中的GridView,Formviews,UserControl等封装在其他UserControl中,以实现可重用性.如果您已经在页面中实现了所有逻辑并使用递归循环访问这些控件,那么很难重构它.如果您已经通过事件处理程序(GridView的RowDataBound)实现了逻辑和访问方法,那么它将更简单,更不容易出错.