简体   繁体   English

在回发时,Repeater的DataTable数据源是否为空?

[英]On Postback, the DataTable data source for a Repeater is empty?

Background 背景

I have a User Control (an .ascx file) which is being dynamically inserting into an asp:PlaceHolder control on a page. 我有一个用户控件(.ascx文件),正在动态插入到页面上的asp:PlaceHolder控件中。 That User Control contains an asp:Repeater, which I'm binding to a DataTable. 该用户控件包含一个asp:Repeater,我将其绑定到DataTable。

Theoretically, on the User Control's first load the DataTable is initialized and 3 empty rows are added. 从理论上讲,在用户控件的第一次加载时,将初始化DataTable并添加3个空行。 A button on the User Control adds additional empty rows to the Repeater, one at a time. 用户控件上的一个按钮一次将一个额外的空行添加到转发器。

Problem 问题

The issue is that after any PostBack event on the page (namely the button in this example being clicked), the DataTable for the Repeater is empty. 问题是,在页面上发生任何PostBack事件(即,单击本示例中的按钮)之后,Repeater的DataTable为空。

User Control (.ascx) (simplified) 用户控件(.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" />

Code Behind (.ascx.cs) (also simplified) 背后的代码(.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();
}

Behavior 行为

The first time the UserControl is loaded, the Repeater contains 3 empty items: good! 第一次加载UserControl时,Repeater包含3个空项目:好! However, after entering some text in the textboxes both inside and outside the repeater and clicking the "Add Item" LinkButton, the page does a refresh/postback and shows 4 empty items, however the textbox -outside- the Repeater retains it's text. 但是,在转发器内部和外部的文本框中输入一些文本并单击“添加项目” LinkBut​​ton之后,页面将进行刷新/回发并显示4个空项目,但是,转发器外部的文本框将保留其文本。 Clicking the "Add Item" LinkButton again also performs a postback and still shows 4 empty items, yet the TextBox outside the Repeater again retains it's text. 再次单击“添加项目” LinkBut​​ton也会执行回发操作,并且仍显示4个空项目,但是Repeater外部的TextBox再次保留其文本。

My Crazy Guess 我的疯狂猜测

I've tried wrapping the Repeater databinding in a (!Page.IsPostBack), but this prevented the Repeater from -ever- being bound, as the UserControl is only programmatically added to the page after a PostBack (a button on the Page adds the UserControl on a click, and then the Page checks each PostBack to see if there should be a user control present and re-adds it to the Page if needed). 我尝试将Repeater数据绑定包装在(!Page.IsPostBack)中,但是这阻止了Repeater的绑定,因为UserControl仅以编程方式添加到PostBack之后(页面上的按钮添加了单击UserControl,然后Page检查每个PostBack,以查看是否应存在用户控件,并在需要时将其重新添加到Page中。 So I'm guessing there's a problem with the Page re-creating the User Control on every PostBack, but can't explain why the TextBox outside the Repeater would retain it's value, and why the ViewState doesn't seem to remember my item (on each postback ViewState["items"] is null and gets re-built within the getter). 因此,我猜想在每个PostBack上重新创建用户控件时,Page都会出现问题,但无法解释为什么Repeater外部的TextBox会保留其值,以及为什么ViewState似乎不记得我的项目(在每个回发上,ViewState [“ items”]为null,并在getter中重新构建)。

HELP! 救命!

The problem is you are data binding every single request when really you only want to data bind on the first request. 问题是当您实际上只想在第一个请求上进行数据绑定时,您正在对每个请求进行数据绑定。 Since you don't data bind on the first page load, you will have to check if you are data bound in a way other than !Page.IsPostBack. 由于在第一页加载时没有数据绑定,因此您将必须检查是否以!Page.IsPostBack以外的方式绑定了数据。 You could add a property to your user control to handle this and then check against that every page load / page init. 您可以在用户控件中添加一个属性来处理此问题,然后针对每个页面加载/页面初始化进行检查。

Update: With more details from comments 更新:注释中有更多详细信息

I see your AddItem() now. 我现在看到您的AddItem()。 I've had problems using viewstate this way though I'm not entirely sure why. 我不确定以这种方式使用viewstate时遇到的问题。 I've had to do it more like the following: 我不得不像下面这样做:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM