2011-11-15 41 views
1

我正在动态创建一个数据绑定DropDownList控件并将其添加到数据绑定中的占位符Repeater控件是一个使用选项卡放置在页面上的自定义用户控件。FindControl不适用于动态创建的用户控件

将DropDownList的ID是动态设置的,和它下面生成的HTML是电路COMP1A

控制的建立和使用工作正常,但是当我尝试递归找到控制,我总是得到空。

这里是生成的HTML:

<select class="formDropDownRating" id="MainContent_ContentPlaceHolder1_TabContainer1_tab1_CE1_Repeater1_Comp1A_0" name="ctl00$ctl00$MainContent$ContentPlaceHolder1$TabContainer1$tab1$CE1$Repeater1$ctl00$Comp1A"> 
    <option value="5">5 - Strongly Agree</option> 
    <option value="4">4 - Agree</option> 
    <option value="3">3 - Somewhat Agree</option> 
    <option value="2">2 - Disagree</option> 
    <option value="1">1 - Strongly Disagree</option> 

</select> 

要找到我打电话

target = FindDropDownListControl("Comp1A"); 

控制

看到杰夫·阿特伍德function

protected DropDownList FindDropDownListControl(string controlReference) 
{ 
    Control root = this.Page.FindControl("ctl00"); //the Master page (the root control) 
    var ddl = (DropDownList)MyApp.Utility.ExtensionMethods.FindControlRecursive(root, controlReference) as DropDownList; 
    return ddl; 
} 

任何人都可以发现什么可能是罪魁祸首?我如何获得Comp1A的参考?

回答

1

我不是100%确定的,因为您的代码示例不包括如何创建控件,但如果我的怀疑是正确的,问题是该控件正在页生命周期中的某个点处创建它在回发中被消灭。

在页面生命周期中,确切地说,控件是创建的?如果它没有在正确的位置创建,或者在周期中太晚,那么它将不会保留在视图状态回传中。

如果可能,请确保它正在Page_Init中创建,或者手动将其添加到Page_Init中。

This article更全面地解释它。

0

您应该总是尝试使用与控件最接近的容器作为根。如果您可以访问中继器或中继器项目,则将其用作根。

如果您不能访问中继器,请尝试使用网页或表格作为根:

protected DropDownList FindDropDownListControl(string controlReference) 
{ 
    var ddl = (DropDownList)MyApp.Utility.ExtensionMethods.FindControlRecursive(Page, controlReference) as DropDownList; 
    return ddl; 
} 
0

我觉得它的外观的类似的东西,

public static T FindControl<T>(this Control control) { 
    T ctrl = default(T); 
    if(control == null) return null; 
    foreach(Control c in control.Controls) { 
     if(ctrl == null) { 
      ctrl = FindControl<T>(c);    
     } 
     else return ctrl; 
    } 
} 

我没有测试它,但您可以将示例与您的需求相匹配。

BTW:您的需要,如果我没有记错它的OnPreRender
比你就能看到结果使用它pageLoad的事件之后。 最好的问候。

0

编辑:我的猜测是,您的页面中还有一些其他控件也具有ID“Comp1A”,并且您的FindControlRecursive方法首先找到该控件。它可能会让你为空,因为该控件不管它是什么,都不是DropDownList。当你做as DropDownList时,结果在这种情况下将为空。

这是我所知道的关于FindControl,以防这对你有任何帮助。

FindControl仅限于同一命名容器(即实现INamingContainer接口的父/祖先控件)内的控件。如果您试图找到位于另一个控件的控件,该控件是与您调用FindControl方法的控件相对的命名容器,则它不会找到它。

页面是一个命名容器,就像UserControl和ContentPlaceHolder一样。我认为TabContainer也是一个命名容器,以及TabContainer中的每个选项卡控件。编辑2:中继器和RepeaterItem(你的中继器的每个“行”将是一个RepeaterItem)都是命名容器。这意味着,如果您从顶部开始查看(即页面),则无法可靠地找到嵌套在中继器中的控件。你需要从同一个RepeaterItem中设置你的起点(本质上这就是詹姆斯约翰逊所建议的)。如果你需要更多的帮助,那么你需要提供更多关于你正在执行的上下文的信息target = FindDropDownListControl("Comp1A");

您的代码从页面开始,尝试挖掘以找到“Comp1A”DropDownList。

this.Master.Master.FindControl("MainContent").FindControl("ContentPlaceHolder1").FindControl("TabContainer1").FindControl("tab1").FindControl("CE1").FindControl("Comp1A") 

(!。哎呀时间太长见下文更短的语法)

:如果这个控制是你的“CE1”用户控件中只是一个普通的控制,那么你可以用类似下面找到它

母版页也作为命名容器,所以这就是为什么我开始使用this.Master而不是this.Page

看起来您正在另一个母版页中使用母版页,因此我已更新我的示例以使用this.Master.Master

据杰夫的职位,你可以使用下面的语法完成同样的事情:

this.Master.Master.FindControl("MainContent:ContentPlaceHolder1:TabContainer1:tab1:CE1:Comp1A") 

然而,正如上面提到的,你正在努力寻找控制是一个中继器内。有一两件事你可以做的是遍历所有的项目在转发,就像这样:

Control repeater = this.Master.Master.FindControl("MainContent:ContentPlaceHolder1:TabContainer1:tab1:CE1:Repeater1"); 

foreach (Control control in repeater.Controls) 
{ 
    var button = control.FindControl("Comp1A"); 
} 

但如果你从中继器的特定行寻找一个特定的“电路COMP1A” DropDownList控件,那么你会需要利用您的上下文才能为您的搜索使用正确的根控件。

相关问题