C#中数据源为List的DataGridView如何实现按列搜索或过滤
问题根因
BindingSource.Filter无效:该属性仅支持实现了IBindingListView接口的数据源(如DataView),普通List<T>未实现对应接口,设置后不会生效。- 转DataTable报空引用:你的DataGridView当前绑定的是
List<Tools>类型,用as DataTable转换会直接返回null,调用其属性自然触发空引用异常。 - 手动建DataTable失败:你没有对
da(SqlDataAdapter)做初始化配置、关联查询语句,无法填充DataTable,且你已经通过Dapper拿到了全量数据,不需要重复查库。
可行解决方案(无绑定修改,符合要求)
该方案直接操作DataGridView行的显示状态,完全不需要修改数据源绑定配置,代码如下:
private void searchTextBox_TextChanged(object sender, EventArgs e) { string searchKey = searchTextBox.Text.Trim(); // 暂停控件重绘,避免搜索时卡顿 dgvAvailableTools.SuspendLayout(); foreach (DataGridViewRow row in dgvAvailableTools.Rows) { // 跳过空白新增行 if (row.IsNewRow) continue; // 此处"Name"替换为你要搜索的列名,也可以用列索引如Cells[0] string cellVal = row.Cells["Name"].Value?.ToString() ?? string.Empty; // 要精确匹配就把Contains改成Equals row.Visible = string.IsNullOrEmpty(searchKey) || cellVal.Contains(searchKey, StringComparison.OrdinalIgnoreCase); } dgvAvailableTools.ResumeLayout(); }
特殊情况处理:如果运行提示「与货币管理器位置关联的行不能被隐藏」,只需在遍历行前加两行代码:
CurrencyManager cm = (CurrencyManager)dgvAvailableTools.BindingContext[dgvAvailableTools.DataSource]; cm.SuspendBinding();在
ResumeLayout()前补充cm.ResumeBinding();即可。
可选优化方案(可接受绑定修改时使用,性能更高)
如果后续不排斥修改绑定数据源,可以把全量工具列表存为全局变量,每次搜索用Linq过滤后重新赋值,性能比遍历行更好:
// 全局存储全量数据 private List<Tools> _allTools; private void SetupDataTableAvailableTool() { _allTools = adapter.GetJoinedToolsData(); dgvAvailableTools.DataSource = _allTools; } private void searchTextBox_TextChanged(object sender, EventArgs e) { string key = searchTextBox.Text.Trim(); dgvAvailableTools.DataSource = string.IsNullOrEmpty(key) ? _allTools : _allTools.Where(t => t.Name.Contains(key, StringComparison.OrdinalIgnoreCase)).ToList(); }
内容的提问来源于stack exchange,提问作者user17463627
相关产品推荐
相关产品推荐

