文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>asp.net中ListView的一个Bug

asp.net中ListView的一个Bug

时间:2010-09-17  来源:杨中科

今天一个学生问了一个问题,他的程序监听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中仍然没有修复。

文章地址:http://connect.microsoft.com/VisualStudio/feedback/details/328680/problem-accessing-controls-clientid-on-asp-net-listviews-itemcreated

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
     }
}



To solve this problem:

1. If possible, access ClientID in DataBound event:
e.g.
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e) {
if (e.Item.ItemType == ListViewItemType.DataItem) {
    Label label1 = (Label)e.Item.FindControl("FirstNameLabel");
    if (label1 != null) {
     string s = label1.ClientID;
     <<< Accessing ClientID is GOOD.
    }
}

2. It is also good to access the FindControl and access ClientID at PreRender

e.g.

public static Control FindControl(string controlId, ControlCollection controls) {
foreach (Control control in controls) {
    if (control.ID == controlId)
     return control;
    if (control.HasControls()) {
     Control nestedControl = FindControl(controlId, control.Controls);
     if (nestedControl != null)
        return nestedControl;
     }
}
return null;
}

protected void ListView1_PreRender(object sender, EventArgs e) {
        
Label label = FindControl("FirstNameLabel", ListView1.Controls) as Label;

if (label != null) {
    string s = label.ClientID;
    <<<< good to access from here
    }
}

**** NOTE: In ASP.NET 2.0 the page hierarchy often happens to be deeper than it was with the older version. Consequently, when you want to obtain a reference to a control of the page given its ID and you don't know at which level of the hierarchy it is placed, using the FindControl() method of the Page object isn't the right way of proceding since it just performs a search among the direct children of the page itself. In such cases you may use a recursive search as shown above.

3. FindControl an access ClientID in Page_Load
e.g.
protected void Page_Load(object sender, EventArgs e) {
Label label = FindControl("FirstNameLabel", ListView1.Controls) as Label;
if (label != null) {
    string s = label.ClientID;
<<< also GOOD to access from here
}
}

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载