0

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

具体来说,我正在生成位于占位符内的下拉列表,该占位符位于中继器内,该中继器位于另一个中继器内,该中继器位于另一个占位符内。

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

我当前的解决方案是遍历每个控件内的所有控件,直到我深入到足以访问下拉列表的:

    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.

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

4

2 回答 2

0

我相信您可以使用$连接容器名称来访问嵌套控件;像这样的东西:

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控件名称,但这似乎适合您,因为您有 1 个验证器可以验证嵌套中继器内的多个控件。

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

于 2012-11-27T03:23:56.100 回答
0

您是否尝试过以递归方式获得控制权?

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; 
} 
于 2012-11-27T03:42:58.713 回答