ASP.NET Repeater按钮点击事件中DataItem为空的问题求助
问题:Repeater按钮点击时Item.DataItem为空,无法获取行数据跳转编辑页
我要实现Repeater中按钮点击时获取对应行数据,拼接URL跳转到编辑页,但点击按钮时item.DataItem为空。Repeater初始绑定正常,能正确显示数据;点击按钮会触发Page_Load,尝试过在点击事件中重新绑定Repeater,问题仍未解决。
原因分析
在ASP.NET回发机制中,Item.DataItem仅在数据绑定阶段(即DataBind()执行时)有效。回发时(比如点击按钮),Repeater不会自动重新绑定数据,因此Item.DataItem会是空值——哪怕手动在点击事件里重新绑定,此时也已经错过数据绑定时机,无法通过DataItem获取数据。
解决方案
方法1:通过CommandArgument传递主键,重新查询数据(推荐)
只需要把主键DealerContactId作为按钮的CommandArgument,点击时用主键重新查询该行完整数据,再拼接URL。这种方式简洁,还能避免在前端暴露大量数据。
修改前端按钮代码:
<asp:Button ID="btnEdit" runat="server" Text="Edit" OnClick="btnEdit_Click" CommandArgument='<%# Eval("DealerContactId") %>' />
修改后台按钮点击事件:
protected void btnEdit_Click(object sender, EventArgs e) { Button btnEdit = (Button)sender; int dealerContactId = Convert.ToInt32(btnEdit.CommandArgument); // 用主键重新查询该行数据,复用现有GetDealerContactInfo方法,或单独实现按ID查询的逻辑 var contact = GetDealerContactInfo().Cast<DataRowView>().FirstOrDefault(r => Convert.ToInt32(r["DealerContactId"]) == dealerContactId); if (contact != null) { ContactTitles title = (ContactTitles)Enum.Parse(typeof(ContactTitles), contact["NameTitleId"].ToString()); bool isChecked = Convert.ToBoolean(contact["DecisionMaker"]); ContactPositions position = (ContactPositions)Enum.Parse(typeof(ContactPositions), contact["DealerContactPositionId"].ToString()); string forename = contact["Forename"].ToString(); string surname = contact["Surname"].ToString(); string phone = contact["PhoneNumber"].ToString(); string direct = contact["DirectDialNumber"].ToString(); string fax = contact["FaxNumber"].ToString(); string mobile = contact["MobileNumber"].ToString(); string email = contact["EmailAddress"].ToString(); string secondEmail = contact["SecondaryEmail"].ToString(); string editUrl = $"EditPage.aspx?dealerContactId={dealerContactId}&title={(int)title}&isChecked={isChecked}&position={(int)position}&forename={Uri.EscapeDataString(forename)}&surname={Uri.EscapeDataString(surname)}&phone={Uri.EscapeDataString(phone)}&direct={Uri.EscapeDataString(direct)}&fax={Uri.EscapeDataString(fax)}&mobile={Uri.EscapeDataString(mobile)}&email={Uri.EscapeDataString(email)}&secondEmail={Uri.EscapeDataString(secondEmail)}"; Response.Redirect(editUrl); } }
方法2:把数据存储在前端隐藏控件中
如果不想重新查询数据库,可以把需要的字段放在前端隐藏控件里,点击时从RepeaterItem中找到这些控件获取值。
修改Repeater的ItemTemplate(将需要的字段改为服务器端隐藏Label):
<ItemTemplate> <tr> <td> <asp:Button ID="btnEdit" runat="server" Text="Edit" OnClick="btnEdit_Click" CommandArgument='<%# Container.ItemIndex %>' /></td> <td style="display:none;"><asp:Label ID="lblDealerContactId" runat="server" Text='<%# Eval("DealerContactId") %>'></asp:Label></td> <td><%# GetTitleText((byte)Eval("NameTitleId")) %></td> <td><%# Eval("Forename") %> <%# Eval("Surname") %></td> <td><asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Eval("DecisionMaker") %>' Enabled="false" /></td> <td><%# GetPositionText((byte)Eval("DealerContactPositionId")) %></td> <td style="display:none;"><asp:Label ID="lblForename" runat="server" Text='<%# Eval("Forename") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblSurname" runat="server" Text='<%# Eval("Surname") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblPhone" runat="server" Text='<%# Eval("PhoneNumber") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblDirect" runat="server" Text='<%# Eval("DirectDialNumber") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblFax" runat="server" Text='<%# Eval("FaxNumber") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblMobile" runat="server" Text='<%# Eval("MobileNumber") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblEmail" runat="server" Text='<%# Eval("EmailAddress") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblSecondEmail" runat="server" Text='<%# Eval("SecondaryEmail") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblNameTitleId" runat="server" Text='<%# Eval("NameTitleId") %>'></asp:Label></td> <td style="display:none;"><asp:Label ID="lblPositionId" runat="server" Text='<%# Eval("DealerContactPositionId") %>'></asp:Label></td> </tr> </ItemTemplate>
修改后台按钮点击事件:
protected void btnEdit_Click(object sender, EventArgs e) { Button btnEdit = (Button)sender; RepeaterItem item = (RepeaterItem)btnEdit.NamingContainer; try { int dealerContactId = Convert.ToInt32(((Label)item.FindControl("lblDealerContactId")).Text); ContactTitles title = (ContactTitles)Convert.ToByte(((Label)item.FindControl("lblNameTitleId")).Text); bool isChecked = ((CheckBox)item.FindControl("CheckBox1")).Checked; ContactPositions position = (ContactPositions)Convert.ToByte(((Label)item.FindControl("lblPositionId")).Text); string forename = ((Label)item.FindControl("lblForename")).Text; string surname = ((Label)item.FindControl("lblSurname")).Text; string phone = ((Label)item.FindControl("lblPhone")).Text; string direct = ((Label)item.FindControl("lblDirect")).Text; string fax = ((Label)item.FindControl("lblFax")).Text; string mobile = ((Label)item.FindControl("lblMobile")).Text; string email = ((Label)item.FindControl("lblEmail")).Text; string secondEmail = ((Label)item.FindControl("lblSecondEmail")).Text; string editUrl = $"EditPage.aspx?dealerContactId={dealerContactId}&title={(int)title}&isChecked={isChecked}&position={(int)position}&forename={Uri.EscapeDataString(forename)}&surname={Uri.EscapeDataString(surname)}&phone={Uri.EscapeDataString(phone)}&direct={Uri.EscapeDataString(direct)}&fax={Uri.EscapeDataString(fax)}&mobile={Uri.EscapeDataString(mobile)}&email={Uri.EscapeDataString(email)}&secondEmail={Uri.EscapeDataString(secondEmail)}"; Response.Redirect(editUrl); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
注意事项
- 方法1更推荐,无需在前端暴露过多数据,避免数据被篡改的风险,通过主键查询保证数据准确性。
- 方法2适合简单场景,但敏感数据不要放在前端隐藏控件中,防止被恶意获取。
内容的提问来源于stack exchange,提问作者Shaun1810
相关产品推荐
相关产品推荐

