【发布时间】:2012-01-31 00:52:03
【问题描述】:
背景
我有一个用户控件(一个 .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 数据绑定包装在 (!Page.IsPostBack) 中,但这阻止了 Repeater 被绑定,因为 UserControl 仅在 PostBack 之后以编程方式添加到页面( Page 在单击时添加 UserControl,然后 Page 检查每个 PostBack 以查看是否应该存在用户控件,并在需要时将其重新添加到 Page)。所以我猜测页面在每个 PostBack 上重新创建用户控件存在问题,但无法解释为什么中继器之外的 TextBox 会保留它的值,以及为什么 ViewState 似乎不记得我的项目(在每个回发 ViewState["items"] 为 null 并在 getter 中重新构建)。
帮助!
【问题讨论】:
标签: c# asp.net user-controls