Asp.net 访问自定义验证器中的嵌套控件

Asp.net 访问自定义验证器中的嵌套控件,asp.net,Asp.net,如何从自定义验证器访问嵌套在页面中的多个级别的asp.net控件 具体来说,我正在生成位于占位符内的DropDownList,占位符位于中继器内,中继器位于另一个中继器内,中继器位于另一个占位符内 我需要访问所有下拉框的选定值以相互比较 我目前的解决方案是循环遍历每个控件内的所有控件,直到我深入到足以访问dropdownlist的: For Each g As Control In sender.Parent.Controls If g.GetType().ToStrin

如何从自定义验证器访问嵌套在页面中的多个级别的asp.net控件

具体来说,我正在生成位于占位符内的DropDownList,占位符位于中继器内,中继器位于另一个中继器内,中继器位于另一个占位符内

我需要访问所有下拉框的选定值以相互比较

我目前的解决方案是循环遍历每个控件内的所有控件,直到我深入到足以访问dropdownlist的:

    For Each g As Control In sender.Parent.Controls
        If g.GetType().ToString.Equals("System.Web.UI.WebControls.Repeater") Then
            For Each k As Control In g.Controls
                If k.GetType().ToString.Equals("System.Web.UI.WebControls.RepeaterItem") Then
                    For Each l As Control In k.Controls
                        If l.GetType().ToString.Equals("System.Web.UI.WebControls.Repeater") Then
                            For Each p As Control In l.Controls
                                If p.GetType().ToString.Equals("System.Web.UI.WebControls.RepeaterItem") Then
                                    For Each n As Control In p.Controls
                                        If n.GetType().ToString.Equals("System.Web.UI.WebControls.PlaceHolder") Then
                                            For Each c As Control In n.Controls
                                                If c.GetType().ToString.Equals("System.Web.UI.WebControls.DropDownList") Then

                                                'Add the dropdownlist to an array so that I can use it after all drop down lists have been added for validation.

这似乎完全是浪费资源。是否有更好的方法从自定义验证器访问这些控件?

我相信您可以使用
$
连接容器名称以访问嵌套控件;大概是这样的:

ControlToValidate="panel1$usercontrol1$otherusercontrol$textbox1"
这确实会导致验证器执行内部
FindControl()
调用,这有点昂贵,因此您应该谨慎使用这种方法

一般来说,访问其他容器中嵌套较深的控件不是一个好主意。您应该将这些控件视为页面/控件的私有成员,而不是以这种方式访问它们。只有当你真的,真的必须这样做时,才使用上述方法

编辑:这可能不是完美的解决方案,但我会这样做。创建一个新的DropDownListX控件(派生自DropDownList),用于抓取页面并检查页面是否实现了您创建的新自定义接口。此接口可用于向页面注册控件,然后验证程序可遍历此列表并验证每个已注册控件。比如:

interface IValidationProvider
{
    void RegisterForValidation ( Control oCtrl );
}
您的页面应该实现此接口。然后在新的DropDownListX控件中:

protected override void OnLoad ( EventArgs e )
{
    IValidationProvider oPage = Page as IValidationProvider;

    if ( oPage != null )
        oPage.RegisterForValidation ( this );
}
然后在页面中,当验证发生时,您可以浏览验证列表中的控件列表并逐个验证它们。您的自定义验证器没有一个
ControlToValidate
控件名,但这似乎适合您,因为您有一个验证器在嵌套的中继器中验证多个控件


此解决方案使您能够完全跳过当前的深循环-如果您有一个需要验证的控件,它将自行注册,否则页面中的列表将为空,无需检查任何内容。这也避免了对控件名进行字符串比较,因为不需要搜索控件-它们会在需要时注册自己。

您是否尝试过递归获取控件

private Control FindControlRecursive(Control root, string id) 
{ 
    if (root.ID == id)
    { 
        return root; 
    } 

    foreach (Control c in root.Controls) 
    { 
        Control t = FindControlRecursive(c, id); 
        if (t != null) 
        { 
            return t; 
        } 
    } 

    return null; 
} 

我不知道控件的id,因为它们是通过多个转发器在aspx文件中生成的。@KevinWasie啊,那就难多了。您是否在中继器内有用户控件,或者您只是将控件直接放在项目模板内?直接放在项目模板内我更新了答案-查看此方法是否适用于您。我以前做过这种设置,效果很好,比使用递归循环搜索控件快得多。当你收到很多请求时,这会有很大的不同。哇,太酷了。我可以想到多个例子,在这些例子中,这个框架将是有益的。谢谢仍然会是系统的一个消耗@xxbbcc方法将针对流量进行扩展。谢谢