为自定义ASP.net服务器控件生成的HTML代码生成子控件的name属性,而不是id属性。像这样:
<span id="GridView2_ctl02_editdis">
<input type="text" name="GridView2$ctl02$editdis$ctl00"/>
</span>
自定义控件本身的ID显然是正确的。
对我来说更奇怪的是,ID确实会生成有时(我不知道在什么条件下)。但是具有该ID的FindControl()
在服务器端返回null。具有name属性值的FindControl()
可以正常工作。
这样的事情:
<span class="TextBox" id="GridView2_ctl02_editdis">
<input type="text" id="GridView2_ctl02_editdis_ctl00" name="GridView2$ctl02$editdis$ctl00"/>
</span>
对于上述情况,FindControl("GridView2$ctl02$editdis$ctl00")
工作正常,FindControl("GridView2_ctl02_editdis_ctl00")
没有。
如何确保一致且可预测的ID?
答案 0 :(得分:3)
他们是一致的。
在内部,作为命名控件(即GridView)子级的控件通过使用“$”附加其父级的ID来构建其完整ID。如果是网格,则为gridID $ rowID $ cellID $ mycontrolID。这对于区分同一子控件的多个实例(即mycontrolID)是必要的。为什么“$”而不是“_”?我猜是因为很多人已经倾向于将他们的控件命名为“my_control_something”,而“$”符号就好了。
因此,GridView2 $ ctl02 $ editdis $ ctl00是正确的ID,这就是它被用作INPUT等控件的名称的原因。发布回发时,框架需要能够将表单键与适当的控件匹配。
我认为,与ID混淆的原因在于,您在.aspx中使用的ID和您在HTML中看到的ID是两回事。客户端ID就是这样。无论出于何种原因,当控件被渲染时(使用ClientID属性),所有“$”都将替换为“_”。我猜这是为了使javascript / css友好。
现在,关于FindControl(“GridView2 $ ctl02 $ editdis $ ctl00”)...你应该尽可能地尝试避免它。 FindControl是一个递归函数,它将“GridView2 $ ctl02 $ editdis $ ctl00”分解为“GridView2”和“ctl02 $ editdis $ ctl00”,找到GridView2并询问它是否具有“ctl02 $ editdis $ ctl00”作为子控件。对于由$。分隔的每个部分重复该过程。
在旁注中,每当你发现自己调用Page.FindControl进行深度掩埋控制时,你需要检查模式并询问原因。例如,无论使用“GridView2 $ ctl02 $ editdis $ ctl00”需要做什么,最有可能需要使用“GridView2 $ ctl02 $ editdis $ ctl01”来完成。在这种情况下,它可能需要在OnItemCreated或OnItemDataBound上处理,在那里您可以访问“知道”“ctl00”的行。