如何根据条件勾选ASP.NET GridView中的复选框?
解决GridView复选框勾选时的“未将对象引用设置到对象实例”错误
问题根源
- 遍历GridView行时未过滤非数据行(如表头行),这类行不存在目标控件,
FindControl会返回null,后续赋值触发空引用异常 - 转换控件后未做null判断,直接访问
Checked属性 - 嵌套循环匹配ID效率低,且未处理Label控件找不到或文本为空的情况
修正方案一:优化Page_Load中的遍历逻辑
修改后台代码,增加行类型判断、控件null校验,并优化ID匹配效率:
public localhost.WebService1 w = new localhost.WebService1(); public localhost.User u = new localhost.User(); if (!IsPostBack) { this.GridView.DataSource = w.SelectListOfIds(); this.GridView.DataBind(); // 将ID数组转为HashSet,提升匹配效率 HashSet<int> userIds = new HashSet<int>(w.SelectListOfIDSOfUser(u.UserId)); foreach (GridViewRow row in GridView.Rows) { // 仅处理数据行 if (row.RowType == DataControlRowType.DataRow) { Label idLabel = row.FindControl("Id") as Label; if (idLabel != null && !string.IsNullOrEmpty(idLabel.Text)) { if (int.TryParse(idLabel.Text, out int cId)) { if (userIds.Contains(cId)) { CheckBox checkbox = row.FindControl("CheckBox1") as CheckBox; // 校验控件存在后再赋值 if (checkbox != null) { checkbox.Checked = true; } } } } } } }
关键优化点:
- 用
HashSet<int>存储ID列表,将嵌套循环的O(n*m)复杂度降为O(n) - 增加
row.RowType == DataControlRowType.DataRow判断,跳过非数据行 - 用
as转换控件后先判断null,避免空引用 - 用
int.TryParse替代Convert.ToInt32,避免格式错误抛出异常
修正方案二:利用RowDataBound事件(更符合WebForm规范)
通过GridView的RowDataBound事件逐行处理,直接从绑定数据中获取ID,无需依赖Label控件:
后台代码
public localhost.WebService1 w = new localhost.WebService1(); public localhost.User u = new localhost.User(); private HashSet<int> _userIds; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { _userIds = new HashSet<int>(w.SelectListOfIDSOfUser(u.UserId)); this.GridView.DataSource = w.SelectListOfIds(); this.GridView.DataBind(); } } protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // 直接从绑定的数据项中获取ID int rowId = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "id")); CheckBox checkbox = e.Row.FindControl("CheckBox1") as CheckBox; if (checkbox != null) { checkbox.Checked = _userIds.Contains(rowId); } } }
前端GridView代码(添加事件绑定)
<asp:GridView ID="GridView" showheader=false runat="server" BorderWidth="1px" CellPadding="4" ForeColor="Black" GridLines="Horizontal" AutoGenerateColumns="false" AllowPaging="true" CssClass="wrapper5" OnRowDataBound="GridView_RowDataBound"> <Columns> <asp:TemplateField> <ItemTemplate> <asp:CheckBox ID="CheckBox1" runat="server"/> </ItemTemplate> </asp:TemplateField> <asp:TemplateField> <ItemTemplate> <asp:Label ID="Id" Text='<%# Eval("id") %>' runat="server"></asp:Label> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView>
该方案优势:逻辑更清晰,直接从绑定数据源取ID,减少控件查找开销和潜在错误。
内容的提问来源于stack exchange,提问作者KK2007
相关产品推荐
相关产品推荐

