HTML“名称” 为 ASP.net 子控件生成的属性,而不是唯一的“ID” 属性
为我的自定义 ASP.net 服务器控件生成的 HTML 代码生成子控件的 name 属性,而不是 id 属性。 像这样的事情:
<span id="GridView2_ctl02_editdis">
<input type="text" name="GridView2$ctl02$editdis$ctl00"/>
</span>
自定义控件本身的 ID 显然是正确的。
对我来说更奇怪的是,ID有时确实会生成(我不知道在什么条件下)。 但是具有该 ID 的 FindControl()
在服务器端返回 null。 FindControl()
与 name 属性的值工作得很好。
像这样的事情:
<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 一致且可预测?
The generated HTML code for my custom ASP.net server control generates the name attribute for child controls, instead of the id attribute. Something like this :
<span id="GridView2_ctl02_editdis">
<input type="text" name="GridView2$ctl02$editdis$ctl00"/>
</span>
The ID for the custom control itself is apparently proper.
What is even stranger for me, is that the ID does get generated sometimes (I do not know under what conditions). But a FindControl()
with that ID returns null on the server side. FindControl()
with the value of the name attribute works just fine.
Something like this :
<span class="TextBox" id="GridView2_ctl02_editdis">
<input type="text" id="GridView2_ctl02_editdis_ctl00" name="GridView2$ctl02$editdis$ctl00"/>
</span>
For the above, FindControl("GridView2$ctl02$editdis$ctl00")
works fine, FindControl("GridView2_ctl02_editdis_ctl00")
doesn't.
How do I ensure consistent and predictable IDs?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
他们是一致的。
在内部,作为命名控件(即 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”的行。
They are consistent.
Internally, controls that are children of a naming control (i.e. GridView), have their full IDs built by appending IDs of their parents using "$". In case of a grid, it's gridID$rowID$cellID$mycontrolID. This is necessary to differentiate between multiple instances of the same child control (i.e. mycontrolID). Why "$" and not "_"? I guess because many people already tend to name their controls "my_control_something" and the "$" symbol is as good as any.
So, the GridView2$ctl02$editdis$ctl00 is the right ID and that's why it's used as a name for controls such as INPUT. When post back occurs, the framework needs to be able to match form keys with appropriate controls.
The confusion with IDs, I think, comes from the fact that an ID you are using inside .aspx and the ID you see in HTML are two different things. The client-side IDs are just that. For whatever reason, when a control gets rendered (using ClientID property), all "$" get replaced with "_". My guess is that this was done to make it javascript/css friendly.
Now, about that FindControl("GridView2$ctl02$editdis$ctl00")... You really should try avoiding it whenever possible. FindControl is a recursive function, which breaks "GridView2$ctl02$editdis$ctl00" into "GridView2" and "ctl02$editdis$ctl00", finds GridView2 and asks if it has the "ctl02$editdis$ctl00" as a child control. The process repeats for each part separated by $.
On a side note, whenever you find yourself calling Page.FindControl for some deeply buried control, you need to examine the pattern and ask why. For instance, whatever needs to be done with the "GridView2$ctl02$editdis$ctl00", most likely needs to be done with a "GridView2$ctl02$editdis$ctl01" as well. In that case, it probably needs to be handled on OnItemCreated or on OnItemDataBound, where you have access to a row who "knows" about "ctl00".