如何隐藏DataGridView中与Access.Text标签不匹配的行?现有代码异常
解决DataGridView筛选时全部行被隐藏的问题
你现在遇到的问题是每次文本框内容变化后所有行都被隐藏,核心原因是你的代码只处理了不匹配行的隐藏操作,却没有把之前被隐藏的、现在可能匹配的行重新设置为可见状态。另外还有个潜在坑:如果单元格值是DBNull,直接调用ToString()会抛出空引用异常。
问题拆解
- 第一次筛选时,你隐藏了不匹配的行;但当你修改文本框内容后,之前被隐藏的行(不管现在是否匹配新文本)都没有被重置可见性,导致旧的隐藏状态叠加新的隐藏操作,最终所有行都被藏起来了
- 未处理单元格值为空的情况,会引发运行时错误
修正后的代码
private void Access_TextChanged(object sender, EventArgs e) { BindingContext[productionBindingSource].SuspendBinding(); string filterText = Access.Text.Trim(); // 去掉首尾空格,避免不必要的匹配失败 foreach (DataGridViewRow row in this.productionDGV.Rows) { // 跳过DataGridView自动生成的新行(如果开启了允许添加新行的功能) if (row.IsNewRow) continue; string cellValue = string.Empty; // 处理单元格值为DBNull的情况,防止报错 if (row.Cells[4].Value != DBNull.Value) { cellValue = row.Cells[4].Value.ToString().Trim(); } // 双向判断:匹配就显示,不匹配就隐藏,覆盖之前的状态 row.Visible = cellValue.Equals(filterText, StringComparison.OrdinalIgnoreCase); // 如果需要严格区分大小写,把上面的判断改成 cellValue == filterText 即可 } BindingContext[productionBindingSource].ResumeBinding(); }
更高效的替代方案
如果你的数据源是DataTable,其实更推荐直接用BindingSource.Filter属性来实现筛选,这种方式不需要手动遍历行,性能更好(数据量大时差距明显),代码也更简洁:
private void Access_TextChanged(object sender, EventArgs e) { string filterText = Access.Text.Trim(); if (string.IsNullOrEmpty(filterText)) { // 清空筛选,显示所有行 productionBindingSource.Filter = string.Empty; } else { // 把下面的"TargetColumnName"替换成你的DataTable中对应列的真实名称 // 处理单引号转义,避免SQL语法错误 string safeFilterText = filterText.Replace("'", "''"); productionBindingSource.Filter = $"TargetColumnName = '{safeFilterText}'"; } }
内容的提问来源于stack exchange,提问作者Linda
相关产品推荐
相关产品推荐

