ASP.NET GridView外按钮复选框判断异常问题求助
问题描述
我有一个包含多行数据的ASP.NET GridView,每行都配置了Checkbox控件,GridView外部设有Approve和Reject两个按钮。需求是:若用户未勾选任何Checkbox就直接点击按钮,需弹出提示框。
但目前存在异常:当GridView中有3行数据,勾选中间行的Checkbox后点击按钮,仍然会弹出"未勾选"的提示框,请问如何解决?
相关代码
前端ASPX代码
<asp:GridView ID="rptHotoIPDataInfo" runat="server" AutoGenerateColumns="false" CssClass="appRejTableOuter appRejTable" Visible="true" AllowPaging="true" PageSize="10" OnPageIndexChanging="rptHotoIPDataInfo_PageIndexChanging" DataKeyNames="SAP_ID" OnRowEditing="rptHotoIPDataInfo_RowEditing" OnRowUpdating="rptHotoIPDataInfo_RowUpdating" OnRowCancelingEdit="rptHotoIPDataInfo_RowCancelingEdit" OnRowDataBound="rptHotoIPDataInfo_RowDataBound" OnRowCommand="rptHotoIPDataInfo_RowCommand" EnableViewState="true"> <Columns> <asp:TemplateField HeaderStyle-CssClass="appRejTable"> <ItemTemplate> <asp:CheckBox ID="chkRow" runat="server" Checked="false" AutoPostBack="true" CssClass="appRejCheckbox" /> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="ID" ItemStyle-Width="50px" Visible="true"> <ItemTemplate> <asp:Label ID="lbl_ID" runat="server" Text='<%#Eval("ID") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Rejected Remarks" HeaderStyle-CssClass="appRejTable"> <ItemTemplate> <asp:TextBox ID="txtRemarks" Rows="3" Text='<%# Eval("REJECT_REMARKS") %>' runat="server" CssClass="appRejInput"></asp:TextBox> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="SAP_ID" HeaderText="SAP ID"></asp:BoundField> <asp:BoundField DataField="CHANGEREQUEST_ID" HeaderText="Change Request ID"></asp:BoundField> <asp:BoundField DataField="R4GSTATE_CODE" HeaderText="State Code"></asp:BoundField> <asp:BoundField DataField="HOTO_STATUS" HeaderText="Hoto Status"></asp:BoundField> <asp:BoundField DataField="CR_Justifications" HeaderText="CR Justifications"></asp:BoundField> <asp:BoundField DataField="APPROVE_REJECT" HeaderText="Status"></asp:BoundField> <asp:BoundField DataField="LAST_UPDATED_BY" HeaderText="Last Updated by"></asp:BoundField> </Columns> </asp:GridView> <asp:Button ID="btnApproveSite" runat="server" CssClass="btn btn-blue" Text="Approve" CommandName="Approve" CommandArgument='<%#Eval("SAP_ID") %>' OnClick="btnApproveSite_Click" /> <asp:Button ID="btnRejectSite" runat="server" CssClass="btn btn-blue" Text="Reject" CommandName="Reject" CommandArgument='<%#Eval("SAP_ID") %>' OnClick="btnRejectSite_Click" />
后台C#代码
protected void btnRejectSite_Click(object sender, EventArgs e) { string strRemarks = string.Empty; string strID = string.Empty; string strCurrentUser = string.Empty; string strBtnReject = string.Empty; bool isUpdateRow = false; foreach (GridViewRow row in rptHotoIPDataInfo.Rows) { if (row.RowType == DataControlRowType.DataRow) { CheckBox chkRow = (row.Cells[0].FindControl("chkRow") as CheckBox); TextBox txtRemarks = (TextBox)row.FindControl("txtRemarks"); strID = (row.Cells[1].FindControl("lbl_ID") as Label).Text; strBtnReject = btnRejectSite.Text; if (chkRow.Checked == true && strBtnReject == "Reject") { strRemarks = txtRemarks.Text; strCurrentUser = CurrentUserName; int intGroupID = CurrentUserGroupID; if (strRemarks != "") { isUpdateRow = UpdateRejectInfo(strID, strRemarks, strCurrentUser, intGroupID, strCurrentUser); if (isUpdateRow) { BindHotoIPNonIPSubmit(); } } else { ScriptManager.RegisterStartupScript(this, typeof(Page), "Alert", "<script>alert('Rejected Remarks cannot be blank');</script>", false); } } else { ScriptManager.RegisterStartupScript(this, typeof(Page), "Alert", "<script>alert('For Rejection, first you need to check the Checkbox');</script>", false); } } } }
解决方案
问题根源
当前代码逻辑错误:遍历GridView每一行时,只要某一行未勾选Checkbox,就会触发else分支弹出提示。比如3行数据中仅中间行勾选,循环到第一行和第三行时,都会执行else里的提示代码,导致即使有勾选行,用户仍会看到未勾选的提示。
修复步骤
- 先遍历所有行,判断是否存在至少一个勾选的Checkbox;
- 如果没有勾选的行,直接弹出提示并终止方法;
- 如果有勾选的行,再遍历处理每一行的勾选逻辑,同时处理备注为空的情况;
- 提示框使用唯一key,避免被后续提示覆盖。
修改后的后台代码
protected void btnRejectSite_Click(object sender, EventArgs e) { string strRemarks = string.Empty; string strID = string.Empty; string strCurrentUser = string.Empty; bool isUpdateRow = false; bool hasCheckedRow = false; // 第一步:检查是否有勾选的行 foreach (GridViewRow row in rptHotoIPDataInfo.Rows) { if (row.RowType == DataControlRowType.DataRow) { CheckBox chkRow = row.FindControl("chkRow") as CheckBox; if (chkRow != null && chkRow.Checked) { hasCheckedRow = true; break; // 找到一个勾选行就停止遍历 } } } // 无勾选行时弹出提示并返回 if (!hasCheckedRow) { ScriptManager.RegisterStartupScript(this, typeof(Page), "Alert_NoCheck", "<script>alert('For Rejection, first you need to check the Checkbox');</script>", false); return; } // 第二步:处理所有勾选的行 foreach (GridViewRow row in rptHotoIPDataInfo.Rows) { if (row.RowType == DataControlRowType.DataRow) { CheckBox chkRow = row.FindControl("chkRow") as CheckBox; TextBox txtRemarks = row.FindControl("txtRemarks") as TextBox; Label lblID = row.FindControl("lbl_ID") as Label; if (chkRow != null && chkRow.Checked) { if (lblID == null || txtRemarks == null) continue; strID = lblID.Text; strRemarks = txtRemarks.Text; strCurrentUser = CurrentUserName; int intGroupID = CurrentUserGroupID; if (string.IsNullOrEmpty(strRemarks)) { // 用唯一key避免提示被覆盖 ScriptManager.RegisterStartupScript(this, typeof(Page), $"Alert_RemarkEmpty_{strID}", "<script>alert('Rejected Remarks cannot be blank');</script>", false); continue; // 跳过当前行,继续处理其他勾选行 } isUpdateRow = UpdateRejectInfo(strID, strRemarks, strCurrentUser, intGroupID, strCurrentUser); if (isUpdateRow) { BindHotoIPNonIPSubmit(); } } } } }
额外优化建议
- 移除Checkbox的
AutoPostBack="true",无实时联动需求时会触发不必要的回发; - 按钮的
CommandArgument='<%#Eval("SAP_ID") %>'无效(按钮不在GridView行内),可直接移除; - 替换原生alert为更友好的模态框提升用户体验。
内容的提问来源于stack exchange,提问作者Nadeem
相关产品推荐
相关产品推荐

