当页面回发时,嵌入ASP.NET ListView的Web控件在ItemDataBound事件处理程序上丢失状态和传递值

问题描述

| 这个问题是关于Web控件的一种非常奇怪的行为。请考虑以下内容。 情境 我有一个Web控件,用于显示一些数据。
MyWebControl.ascx
文件如下:
<%@ Control ViewStateMode=\"Enabled\" 
            Language=\"C#\" 
            AutoEventWireup=\"true\" 
            CodeFile=\"MyWebControl.ascx.cs\" 
            Inherits=\"MyWebControl\" %>

<div>
   <asp:Label ID=\"MyLabel1\" runat=\"server\"></asp:Label>
   <asp:Label ID=\"MyLabel2\" runat=\"server\"></asp:Label>
</div>
MyWebControl.ascx.cs
后面的代码是:
public partial class MyWebControl : 
      System.Web.UI.UserControl {
   protected string str1;
   protected string str2;

   public string Str1 {
      get { return this.str1; }
      set { this.str1 = value; }
   }
   public string Str2 {
      get { return this.str2; }
      set { this.str2 = value; }
   }

   protected void Page_Load(object sender,EventArgs e) {
      this.MyLabel1.Text = this.str1;
      this.MyLabel2.Text = this.str2;
   }
}
好吧,我以普通的Web形式在一个
ListView
的矿井中使用此控件。此网络表单称为
Default.aspx
,接下来,我展示其代码的一部分,仅显示
ListView
所在的代码
<%@ Page Title=\"My page\" Language=\"C#\" AutoEventWireup=\"true\"
         CodeFile=\"Default.aspx.cs\" Inherits=\"_Default\" %>

<%@ Register TagPrefix=\"my\" TagName=\"MyWC\" Src=\"~/MyWebControl.ascx\" %>
...
...
<div>
   <asp:ListView ID=\"MyLV_ListView\" runat=\"server\" 
                 EnableViewState=\"true\" 
                 OnPreRender=\"MyLV_ListView_PreRender\" 
                 OnItemDataBound=\"MyLV_ListView_ItemDataBound\">
      <ItemTemplate>
         <my:MyWC ID=\"WC_MyWC\" runat=\"server\" />
      </ItemTemplate>
   </asp:ListView>
</div>
web8ѭ背后的Web表单代码为:
public partial class _Default : System.Web.UI.Page {
   protected void Page_Load(object sender,EventArgs e) {
      if (!this.IsPostBack) {
         DAO d = new DAO(...); /* This object will contain some data */
                               /* Data are somehow paged,changing index,we have other data */
                               /* Please do not worry about paging,it works,problem is another */
         d.PageIndex = 0;
         this.ViewState[\"DAO\"] = d; /* DAO is serializable */
         this.ViewState[\"PageIndex\"] = 0;
         Data[] data = d.GetData(); /* Returns an array of objects representing my data */
                                    /* Custom way of storing data in objects */
                                    /* GetData use the PageIndex to get only a range of results */
         this.MyLV_ListView.DataSource = data;
         this.MyLV_ListView.DataBind();
      }
   }
   protected void MyLV_ListView_ItemDataBound(object sender,ListViewItemEventArgs e) {
      if (e.Item.ItemType == ListViewItemType.DataItem) {
         ((MyWebControl)e.Item.FindControl(\"WC_MyWC\")).Str1 = 
            ((Data)e.Item.DataItem).datafield1;
         ((MyWebControl)e.Item.FindControl(\"WC_MyWC\")).Str2 = 
            ((Data)e.Item.DataItem).datafield2;
      }
   }
   protected void MyLV_ListView_PreRender(object sender,EventArgs e) {
      if (this.IsPostBack)
         this.MyLV_ListView.DataBind();
   }
   // A TreeView will cause the page to reload,// this is the handler called when a tree node is 
   // selected,the node is used to change the page 
   // for showing data in my listview.
   protected void MyLVPaging_TreeView_SelectednodeChanged(object sender,EventArgs e) {
      this.ViewState[\"PageIndex\"] = int.Parse(this.MyLVPaging_TreeView.Selectednode.Value);
      ((DAO)this.ViewState[\"DAO\"]).PageIndex = (int)this.ViewState[\"PageIndex\"];
      // After setting the new index,GetData will return another set of results
      this.MyLV_ListView.DataSource = ((DAO)this.ViewState[\"DAO\"]).GetData();
   }
}
问题 我有什么问题??? 好吧,当页面第一次加载时,我可以在列表视图中看到一些数据,因此一切正常。 当我选择另一个页面时,会导致页面重新加载并回发...我的
ListView
显示正确的条目数,但其中没有数据。 Web控件的放置次数与检索到的数据记录的数量相同,但是Web控件中没有数据。 调试结果 我进行了一些调试会议,这是发生了什么,请跟我来,我想这非常重要。 首次加载页面 1)执行
Load
页面方法。 2)执行
ListView
ItemDataBound
事件处理程序。好吧,假设我在
DataSource
Data[]
数组中有三个元素,则该处理程序被调用了3次。在继续调试该方法时检查值,可以看到
((Data)e.Item.DataItem).datafield1
((Data)e.Item.DataItem).datafield2
是从
ListView
中的绑定数据源检索的正确值。 执行该方法后,调试器光标移至控件的
Page_Load
方法
MyWebControl.ascx.cs
。通过检查变量,我可以看到发生了这种情况:
protected void Page_Load(object sender,EventArgs e) {
   this.MyLabel1.Text = this.str1; // <-- this.str1 has the correct value loaded in the list view itemdatabound event handler.
   this.MyLabel2.Text = this.str2; // <-- this.str2 has the correct value loaded in the list view itemdatabound event handler.
}
3)调用
ListView
PreRender
方法。 4)页面显示,一切正常! 在TreeView中选择节点后页面回发 1)执行
Load
页面方法,但不执行任何操作。 2)执行
MyLVPaging_TreeView_SelectednodeChanged
在这里,我可以看到所有内容都具有正确的值: 受保护的void MyLVPaging_TreeView_SelectednodeChanged(object sender,EventArgs e){    this.ViewState [\“ PageIndex \”] =       int.Parse(this.MyLVPaging_TreeView.Selectednode.Value); // <-新页面    ((DAO)this.ViewState [\“ DAO \”])。PageIndex =       (int)this.ViewState [\“ PageIndex \”]; // <-索引已保存    //设置新索引后,GetData将返回另一组结果    this.MyLV_ListView.DataSource =       ((DAO)this.ViewState [\“ DAO \”])。GetData(); // <-数据源已更改 } 3)执行
ListView
ItemDataBound
事件处理程序。好吧,在这里,调试我可以看到与以前相同的意思,我的意思是,我看到新的值,新的
Data
已绑定到
ListView
,实际上,我可以检查分配给模板项目的新值。 显然,和以前一样,执行该方法后,调试器光标将移至控件的
Page_Load
方法
MyWebControl.ascx.cs
。 邪恶:我可以看到以下内容
protected void Page_Load(object sender,EventArgs e) {
   // Note: inspecting this.IsPostBack I get true!
   this.MyLabel1.Text = this.str1; // <-- this.str1 is null and also this.MyLabel1.Text is null.
   this.MyLabel2.Text = this.str2; // <-- this.str2 is null and also this.MyLabel1.Text is null. view itemdatabound event handler.
}
  好!!!它丢失状态和其他值   通过列表视图   处理者!!!!!!!!! 我的问题 这到底是怎么回事??? 笔记 1)请不要过多地关注我如何管理
Load
PreRender
事件上的数据绑定...我觉得这不是错误!我想这与页面生命周期有关。但是,如果您认为这很重要,请告诉我。 2)ѭ35和它的功能
GetData()
是让您尽可能快地理解场景的一种方法,该场景稍微多了一些,但是结构与我在此处显示的相同。 谢谢您的帮助。     

解决方法

        从我的评论:   你为什么不动   来自this.MyLV_ListView.DataBind()   预渲染到SelectedNodeChanged?和   为什么需要字段str1和   您的UserControl中的str2?物业   Str1应该获取/设置this.MyLabel1.Text   和属性Str2应该获得/设置   this.MyLabel2.Text,因为   标签\的文本已经存储在   ViewState。 安德烈:   ...因此这些设置不是   要在负载中制造? 我:   您不需要等待任何事件   碰巧设置标签的文本。的   属性应直接导致   相应的标签,因此您的   字段str1和str2是冗余的。   他们将被处置在   页面生命周期与   标签的文本属性是   自动存储在ViewState中   跨回发。     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...