VB.NET WinForm组合框SelectedIndexChanged事件报空引用异常
- 开发工具:VS 2012
- 技术栈:VB.NET、WinForms桌面应用
切换combo_company组合框选项触发SelectedIndexChanged事件时,程序抛出System.NullReferenceException空引用异常。开发时尝试获取combo_company.SelectedItem与combo_company.SelectedValue属性值,先后采用两种方式实现组合框数据绑定,两种方式运行表现不一致。
两种绑定方式共用的数据库查询代码如下:
Dim da As New SqlDataAdapter Dim cmd As New SqlCommand Dim dt As New DataTable cmd.Connection = con Dim sql As String = "select company_name, company_id from tbl_company" cmd = New SqlCommand(sql, con) If con.State = ConnectionState.Open Then con.Close() con.Open() da = New SqlDataAdapter(cmd) da.Fill(dt)
第一种:循环遍历DataTable手动添加项
实现代码:
combo_company.DisplayMember = "company_name" combo_company.ValueMember = "company_id" If dt.Rows.Count >= 1 Then For i = 0 To dt.Rows.Count - 1 combo_company.Items.Add(dt.Rows(i).Item(0).ToString) Next End If
运行表现:
combo_company.SelectedItem可正常获取取值- 访问
combo_company.SelectedValue时抛出System.NullReferenceException异常
第二种:直接绑定DataTable作为数据源
实现代码:
combo_company.DisplayMember = "company_name" combo_company.ValueMember = "company_id" combo_company.DataSource = dt
运行表现:
combo_company.SelectedItem返回System.Data.DataRowView类型对象combo_company.SelectedValue可正常获取取值
第一种绑定方式的问题根源
DisplayMember和ValueMember属性仅在组合框绑定DataSource数据源时生效。手动调用Items.Add()往集合里添加纯字符串对象时,组合框不会识别预设的ValueMember配置,也不会存储与字符串对应的company_id值,因此SelectedValue始终为null,访问时自然触发空引用异常。
如果要使用手动加项的模式,需要自行维护名称与ID的映射关系,例如通过Dictionary(Of String, Integer)存储公司名和对应ID,选中时通过SelectedItem的文本值查字典拿ID,不要访问SelectedValue属性。第二种绑定方式的注意事项
直接绑定DataTable到DataSource是WinForms组合框数据绑定的标准用法,返回DataRowView类型的SelectedItem是正常表现:
- 若要获取选中的公司名称,直接读取
combo_company.Text属性即可,无需转换SelectedItem类型 SelectedValue会直接返回配置的company_id字段值,可直接使用
- 通用空引用规避方案
SelectedIndexChanged事件会在组合框初始化绑定阶段多次触发,此时选中项尚未赋值,容易触发空引用。建议在事件处理方法最开头加入空判断:
Private Sub combo_company_SelectedIndexChanged(sender As Object, e As EventArgs) Handles combo_company.SelectedIndexChanged ' 初始化阶段无有效选中项时直接跳过逻辑 If combo_company.SelectedValue Is Nothing Then Return End If ' 此处编写正常业务逻辑 End Sub
另外绑定数据源时,固定按照「先设置DisplayMember和ValueMember,最后赋值DataSource」的顺序编写,可减少不必要的事件触发次数。
内容的提问来源于stack exchange,提问作者Umesh

