ASP.NET中如何访问ListView内的CheckBox?FindControl报错未实例化
问题根本原因
- 控件查找时机错误:你在执行
lvNotas.DataBind()之前就调用FindControl查找CheckBox,此时ListView还没有根据数据源生成子行和模板内的控件,返回值为null,调用null对象的属性就会抛出对象未实例化错误。 - 查找范围错误:
testecb是定义在ItemTemplate内的控件,属于每个ListView数据行的子控件,直接对ListView控件本身调用FindControl只能查找ListView顶层的控件,无法定位到模板内的子控件。
修复方案
推荐使用ListView的ItemDataBound事件处理模板内控件的状态设置,这是ASP.NET数据绑定控件处理模板内容的标准实现方式:
步骤1:修改现有的按钮点击逻辑
把查找控件、设置CheckBox的逻辑移除,先完成数据绑定:
protected void btnPesquisar_Click(object sender, EventArgs e) { limpaCampos(); using (PrincipalDataContext pdc = new PrincipalDataContext()) { if (!string.IsNullOrEmpty(txtCodRomaneio.Text)) { var romaneios = pdc.z_stp_anb_transp_receb(Convert.ToInt32(txtCodRomaneio.Text)).ToList(); if (romaneios != null && romaneios.Any()) { lvNotas.DataSource = romaneios; lvNotas.DataBind(); } else { ScriptManager.RegisterStartupScript(this, typeof(Page), UniqueID, "alert('Romaneio não encontrado!')", true); } } } }
步骤2:给ListView添加ItemDataBound事件
首先在前端的ListView控件属性上添加事件绑定:OnItemDataBound="lvNotas_ItemDataBound"
然后在后台代码中添加事件处理方法:
protected void lvNotas_ItemDataBound(object sender, ListViewItemEventArgs e) { // 仅处理数据行,跳过页眉、页脚等其他类型的行 if (e.Item.ItemType == ListViewItemType.DataItem) { // 获取当前行绑定的原始数据 var currentItem = (dynamic)e.Item.DataItem; // 查找当前行内的CheckBox控件 CheckBox check = e.Item.FindControl("testecb") as CheckBox; // 非空判断避免异常 if (check != null && currentItem.status == 1) { check.Checked = true; check.Enabled = false; } } }
如果你的数据是强类型实体,把上面代码中的dynamic替换为你的实际实体类即可获得编译时类型检查,安全性更高。
替代方案(数据绑定后遍历行设置)
如果你不想额外添加事件,也可以在数据绑定完成后直接遍历ListView的所有行进行设置:
lvNotas.DataSource = romaneios; lvNotas.DataBind(); // 绑定完成后遍历所有行 var r = romaneios.First(); foreach (ListViewDataItem item in lvNotas.Items) { CheckBox check = item.FindControl("testecb") as CheckBox; if (check != null && r.status == 1) { check.Checked = true; check.Enabled = false; } }
内容的提问来源于stack exchange,提问作者Leonardo Vangelista
相关产品推荐
相关产品推荐

