在Postback上,中继器的DataTable数据源为空

本文关键字:DataTable 数据源 中继器 Postback | 更新日期: 2023-09-27 18:21:52

背景

我有一个用户控件(.ascx文件),它正在动态插入页面上的asp:PlaceHolder控件中。该用户控件包含一个asp:Repeater,我将其绑定到一个DataTable。

理论上,在用户控件的第一次加载时,DataTable被初始化,并添加了3个空行。用户控件上的一个按钮向中继器添加额外的空行,一次添加一行。

问题

问题是,在页面上的任何PostBack事件(即单击本例中的按钮)之后,Repeater的DataTable都是空的。

用户控件(.ascx)(简化)

<asp:TextBox ID="controlOutsideRepeater" runat="server" />
<asp:Repeater ID="myRepeater" runat="server">
  <ItemTemplate>
    <p><asp:Textbox ID="firstControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "A") %>' /></p>
    <p><asp:Textbox ID="secondControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "B") %>' /></p>
  </ItemTemplate>
</asp:Repeater>
<asp:LinkButton ID="addItemButton" runat="server" Text="Add Item" onclick="addNewItem" />

代码隐藏(.ascx.cs)(也简化了)

public DataTable items {
  get {
    object i = ViewState["items"];
    if (i == null) {
      DataTable t = new DataTable();
      t.Columns.Add("A");
      t.Columns.Add("B");
      // add 3 blank items/rows:
      t.Rows.Add(t.NewRow());
      t.Rows.Add(t.NewRow());
      t.Rows.Add(t.NewRow());
      ViewState["items"] = t;
      return t;
    } else {
      return (DataTable)i;
    }
  set { ViewState["items"] = value; }
}
protected void Page_Init(object sender, EventArgs e) {
  myRepeater.DataSource = this.items;
  myRepeater.DataBind();
}
public void addNewItem(object sender, EventArgs e) {
  DataRow r = this.items.NewRow();
  this.items.Rows.Add(r);
  myRepeater.DataBind();
}

行为

第一次加载UserControl时,Repeater包含3个空项:好!然而,在中继器内外的文本框中输入一些文本并单击"添加项目"链接按钮后,页面会进行刷新/回发,并显示4个空项目,但中继器外部的文本框会保留其文本。再次单击"添加项目"链接按钮也会执行回发,并且仍然显示4个空项目,但Repeater外部的TextBox再次保留其文本。

我的疯狂猜测

我曾尝试将Repeater数据绑定包装在(!Page.IsPostBack)中,但这阻止了Repeater的绑定,因为UserControl仅在PostBack之后以编程方式添加到页面中(页面上的按钮单击即可添加UserControl,然后页面检查每个PostBack以查看是否应该存在用户控件,并在需要时将其重新添加到页面)。因此,我猜测页面在每个PostBack上重新创建用户控件存在问题,但无法解释为什么Repeater外部的TextBox会保留它的值,以及为什么ViewState似乎不记得我的项目(在每个PostBack上,ViewState["items"]为空,并在getter中重新构建)。

救命!

在Postback上,中继器的DataTable数据源为空

问题是,当您真正只想在第一个请求上进行数据绑定时,您正在对每个请求进行数据绑定。由于您在加载第一个页面时没有数据绑定,因此必须检查您是否以其他方式绑定了数据!Page.IsPostBack。你可以向你的用户控件添加一个属性来处理这个问题,然后在每次页面加载/页面初始化时检查它。

更新:通过评论获得更多详细信息

我现在看到你的AddItem()了。我在使用视图状态时遇到了问题,尽管我不完全确定原因。我不得不这样做:

public void addNewItem(object sender, EventArgs e) {
  DataTable theItems = this.items;
  DataRow r = theItems.NewRow()
  theItems.Rows.Add(r);
  this.items = theItems
  myRepeater.DataBind(); //I'm not sure if this belongs here because of the reasons said before
}