今天一个学生问了一个问题,他的程序监听ListView的ItemCreated事件,然后在事件响应函数中用FindControl定位InsertTemplate中的控件,然后使用控件的ClientID进行JavaScript的注册:
if (e.Item.ItemType == ListViewItemType.InsertItem) {
TextBox TextBox1 = (TextBox)e.Item.FindControl("FirstNameTextBox");
但是运行以后发现取到的ClientID和最终渲染到浏览器的ID不一样,经过我搜索,在微软的网站上找打了官方解释,确实是ListView的一个Bug,这个Bug在ASP.Net 4.0中仍然没有修复。
On any ASP.NET ListView's ItemCreated event.
If one trying to access "ClientID" property of a certain control
inside ListView's InsertItemTemplate.
The actual client ID of that control, when it is rendered into HTML, will be corrupted
and hence the postback of that control won't fire any event
or the data cannot be bound.
微软的回复:
Thanks for reporting this issue. There is a bug in how System.Web.UI.Control caches its UniqueID if it has been accessed before its NamingContainer has been added to the control tree. This is exactly the bug you are seeing -- your custom control accesses its UniqueID property before its parent GenericWebPart (a NamingContainer) has been added to the control tree.
Unfortunately, due to performance and compatibility concerns, we are unable to fix the root cause of this issue in System.Web.UI.Control. Here are the workaround that may help your scenario:
Your current code:
protected void ListView1_ItemCreated(object sender, ListViewItemEventArgs e) {
if (e.Item.ItemType == ListViewItemType.InsertItem) {
TextBox TextBox1 = (TextBox)e.Item.FindControl("FirstNameTextBox");
if (TextBox1 != null) {
string s = TextBox1.ClientID;
<<< Error: accessing ClientID here as too early in the page lifecycle
}
}
微软给出的解决方案是使用ItemDataBound事件,但是ItemDataBound事件中不能处理InsertTemplate中的内容。我的解决方案是,虽然找到的控件的ClientID和最终生成的不一样,但是仍然能够保证唯一性,因此可以给控件设置一个额外的属性,比如myId,然后用JQuery来通过这个myId来定位控件,大体思路:
textbox1.Attributes["myId"] = textbox1.ClientID;
textbox2.Attributes["onblur"] = "$('input[myId="+textbox1.ClientID+"').text('test')";
或者完全用JQuery的next之类的方法进行定位不依赖于ID。
如鹏网.Net培训班正在报名,有网络的地方就可以参加如鹏网的学习,学完就能高薪就业,点击此处了解
三年前只要懂“三层架构”就可以说“精通分层架构”;现在则需要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值钱;
三年前只要会SQLServer就可以说自己“精通数据库开发”;现在则需还需要掌握MySQL等开源数据库才能说是“.Net开源”时代的程序员;
三年前只要会进行用户上传内容的安全性处理即可;现在则需要熟悉云存储、CDN等才能在云计算时代游刃有余;
三年前只要掌握Lucene.Net就会说自己“熟悉站内搜索引擎开发”;现在大家都用ElasticSearch了,你还用Lucene.Net就太老土了;
三年前发邮件还是用SmtpClient;现在做大型网站发邮件必须用云邮件引擎;
三年前缓存就是Context.Cache;现在则是Redis、Memcached的天下;
如鹏网再次引领.Net社区技术潮流!点击此处了解如鹏网.Net最新课程