C# WinForm中DataGridView搜索及父窗体文本框填充问题求助
解决方案:DataGridView动态搜索+双击填充父窗体文本框
一、解决搜索时的异常问题
1. 异常根源分析
- 前两段代码的
NullReferenceException:dgvRegistration.DataSource并非DataTable类型,或是未完成赋值,直接强制转换会得到null。 - 第三段代码的
InvalidCastException:错误将DataView类型的数据源强制转为DataSet,类型不匹配导致转换失败。
2. 正确的搜索实现代码
兼容常见的数据源绑定类型(DataTable/DataView/BindingSource),同时避免空引用和语法错误:
private void txtSearch_TextChanged(object sender, EventArgs e) { // 先判断数据源是否存在 if (dgvRegistration.DataSource == null) return; DataTable targetTable = null; // 根据实际绑定类型提取DataTable if (dgvRegistration.DataSource is DataTable table) { targetTable = table; } else if (dgvRegistration.DataSource is DataView view) { targetTable = view.Table; } else if (dgvRegistration.DataSource is BindingSource bs) { targetTable = bs.DataSource as DataTable; targetTable ??= (bs.DataSource as DataView)?.Table; } // 确保拿到有效DataTable后设置过滤规则 if (targetTable != null) { // 转义单引号,避免过滤表达式语法错误 string safeSearchText = txtSearch.Text.Replace("'", "''"); // 空搜索时清空过滤,否则执行模糊匹配(可改为'{0}%'实现前缀匹配) targetTable.DefaultView.RowFilter = string.IsNullOrEmpty(safeSearchText) ? string.Empty : $"RegID LIKE '%{safeSearchText}%'"; } }
关键注意事项
- 必须先校验
DataSource是否为空,从源头避免空引用 - 兼容三种常见的WinForms数据源绑定类型
- 转义搜索文本中的单引号,防止因特殊字符导致过滤表达式失效
二、双击DataGridView填充父窗体文本框
根据窗体打开方式的不同,提供两种实现方案:
1. 模态对话框场景
在搜索窗体中定义公共属性存储选中值,双击时赋值并关闭窗体:
// 搜索窗体类内部 public string SelectedRegID { get; private set; } private void dgvRegistration_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { // 排除表头行点击 if (e.RowIndex >= 0) { SelectedRegID = dgvRegistration.Rows[e.RowIndex].Cells["RegID"].Value.ToString(); this.DialogResult = DialogResult.OK; this.Close(); } }
父窗体中调用搜索窗体并接收结果:
private void btnOpenSearch_Click(object sender, EventArgs e) { using (var searchForm = new SearchForm()) { if (searchForm.ShowDialog() == DialogResult.OK) { txtParentRegID.Text = searchForm.SelectedRegID; // 如需填充更多字段,扩展公共属性即可 } } }
2. 非模态窗体场景
通过事件委托传递选中数据:
// 搜索窗体类内部 public event Action<string> OnRegIDSelected; private void dgvRegistration_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0) { string regID = dgvRegistration.Rows[e.RowIndex].Cells["RegID"].Value.ToString(); OnRegIDSelected?.Invoke(regID); // 可选:关闭搜索窗体 // this.Close(); } }
父窗体中订阅事件并接收数据:
private void btnOpenSearch_Click(object sender, EventArgs e) { var searchForm = new SearchForm(); searchForm.OnRegIDSelected += regID => txtParentRegID.Text = regID; searchForm.Show(); }
三、额外排查建议
- 确认
dgvRegistration的数据源绑定时机,确保在搜索操作前已完成数据加载(例如在窗体Load事件中初始化) - 如果绑定的是自定义实体列表,无法使用
RowFilter,需改用LINQ过滤后重新绑定(根据你的异常信息,当前应为Data类数据源,可忽略此条)
内容的提问来源于stack exchange,提问作者TEHSEEN KHAN
相关产品推荐
相关产品推荐

