2012-01-31 46 views
1

背景在回发上,Repeater的DataTable数据源为空?

我有个用户控件(一个.ascx文件),其被动态插入到一个asp:在页面上占位符控制。该用户控件包含一个asp:Repeater,我绑定到一个DataTable。

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

问题

问题是,页面上的任何回发事件(即在本例中被点击的按钮)后,对中继数据表是空的。

用户控件(.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个空项目:好!然而,在转发器内外的文本框中输入一些文本并单击“添加项目”LinkBut​​ton后,页面会执行刷新/回发并显示4个空项目,但文本框外侧 - Repeater保留其文本。再次单击“添加项目”LinkBut​​ton也会执行回发并仍显示4个空项目,但Repeater外部的TextBox会再次保留其文本。

我的疯狂猜测

我已经试过包装在一个(!Page.IsPostBack)直放站绑定,但是这阻止了中继从-ever-的束缚,为用户控件只能以编程方式添加到PostBack之后的页面(页面上的按钮单击添加UserControl,然后页面会检查每个PostBack以查看是否应该存在用户控件,并在需要时将其重新添加到页面中)。所以我猜测页面在每个PostBack上重新创建用户控件都存在问题,但无法解释为什么Repeater外部的TextBox会保留它的值,以及为什么ViewState似乎不记得我的项目(在每个回发ViewState [“项目”]为空,并在getter内重新构建)。

帮助!

回答

1

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

更新:从意见

更多的细节我看到你的AddItem()现在。尽管我并不完全确定为什么,但我仍然用这种方法使用viewstate时遇到了问题。我必须做得更像下面这样:

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

感谢您的回复。我试图通过在我的页面上添加一个空标签,并在Page_Load上检查标签的文本是否为空。如果为空,我为标签设置一个文本值并执行我的数据绑定(我注释掉了Page_Init中的数据绑定),如果标签具有文本值,我将跳过数据绑定。其结果是中继器第一次正确绑定(带有3个空项目),但在后续回发中完全没有绑定。在这里的一些搜索表明,中继器需要绑定每个请求... – DaveD 2012-01-31 01:10:58

+0

我不知道中继器的这种行为。 MSDN上的这篇文章举例说明了一个if!IsPostBack块中发生的所有绑定。 http://msdn.microsoft.com/en-us/library/s1th73f0.aspx我唯一的猜测是视图状态没有被更新或正确读取。这听起来像它的绑定罚款,如果你有3空白行。问题是viewstate每次都是空的。你什么时候回写ViewState(除了你设置的方法)? – SpartanDonut 2012-01-31 01:19:04

+0

只是在getter和setter中,并间接地在addItem()事件处理函数中(因为它调用setter) – DaveD 2012-01-31 01:25:25