You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用LINQ过滤DataGridView时空值报错、逻辑反向问题求解

问题根因
  • 空引用报错:你的LINQ查询用了多组左连接,关联表无匹配数据时对应字段值为null,DataGridView单元格Value会是null或DBNull.Value,直接调用ToString()必然触发空引用异常。
  • 过滤结果反向:现有代码逻辑是找到匹配筛选条件的行,把这些行设为隐藏,完全和需求相反;同时两个筛选条件的判断逻辑独立,第二个条件的else分支会在未选择检验人筛选项时,把所有行重置为可见,直接覆盖前面类别的筛选结果。
  • 隐藏bug:你代码中取检验人列用的列名是inspector,但LINQ查询输出的匿名类中对应字段名是inspected_by,本身就会找不到列报错。
修复方案

你可以任选以下一种方案实现,第二种数据源过滤方案稳定性和性能更优。

方案1:修正原有行可见性控制逻辑

直接修复你现有代码的逻辑问题,处理空值、修正判断方向、补全多条件协同逻辑:

// 先获取选中的筛选值
string selectCat = cbx_category.Text.Trim();
string selectInsp = cbx_inspector.Text.Trim();

// 遍历所有非新行判断可见性
foreach (DataGridViewRow row in dtg_Data.Rows.OfType<DataGridViewRow>())
{
    if (row.IsNewRow) continue;

    // 类别筛选判断,默认匹配
    bool catPass = true;
    if (selectCat != "Category")
    {
        object catVal = row.Cells["category"].Value;
        string catText = catVal == null || catVal == DBNull.Value ? string.Empty : catVal.ToString().Trim();
        catPass = catText == selectCat;
    }

    // 检验人筛选判断,默认匹配
    bool inspPass = true;
    if (selectInsp != "Inspector")
    {
        // 注意列名是inspected_by,不是inspector
        object inspVal = row.Cells["inspected_by"].Value;
        string inspText = inspVal == null || inspVal == DBNull.Value ? string.Empty : inspVal.ToString().Trim();
        inspPass = inspText == selectInsp;
    }

    // 两个筛选条件都通过才显示
    row.Visible = catPass && inspPass;
}

方案2:数据源级过滤(推荐)

由于你是通过DataSource绑定数据,直接在内存中过滤全量数据再重新绑定,比操作DataGridView行状态更稳定,不会出现控件行状态相关的异常。

  1. 首先在窗体类中定义全局变量,存储查询得到的全量数据:
// 存储全量未过滤数据,因为是匿名类先存为dynamic列表,后续自定义强类型模型替换更稳妥
private List<dynamic> _fullDataSource;
  1. 修改你原来的数据加载代码,将查询结果存入全局变量再绑定:
var result = (from t1 in db.tbl_item_lists
              // 保留你原来的所有左连接逻辑,完全不用改
              join t2 in db.tbl_uoms on t1.uom equals t2.uom_id into t12
              from t121 in t12.DefaultIfEmpty()
              join t3 in db.tbl_mode_procs on t1.mode_of_procurement equals t3.mop_id into t13
              from t131 in t13.DefaultIfEmpty()
              join t4 in db.tbl_inspectors on t1.inspected_by equals t4.inspector_id into t14
              from t141 in t14.DefaultIfEmpty()
              join t5 in db.tbl_representatives on t1.ofm_representative equals t5.representative_id into t15
              from t151 in t15.DefaultIfEmpty()
              join t6 in db.tbl_receivers on t1.received_by equals t6.receiver_id into t16
              from t161 in t16.DefaultIfEmpty()
              join t7 in db.tbl_status on t1.status equals t7.status_id into t17
              from t171 in t17.DefaultIfEmpty()
              join t8 in db.tbl_categories on t1.category equals t8.category_id into t18
              from t181 in t18.DefaultIfEmpty()
              select new
              {
                  barcode = t1.barcode,
                  item_name = t1.item_name,
                  description = t1.description,
                  date_procured = t1.date_procured,
                  category = t181.category,
                  part_number = t1.part_number,
                  serial_number = t1.serial_number,
                  batch_number = t1.batch_number,
                  last_borrower = t1.last_borrower,
                  purpose = t1.purpose,
                  date_returned = t1.date_returned,
                  uom = t121.uom,
                  quantity = t1.quantity,
                  mode_of_procurement = t131.mode_proc,
                  price = t1.price,
                  inspected_by = t141.full_name,
                  ofm_representative = t151.full_name,
                  received_by = t161.full_name,
                  contract = t1.contract,
                  proponent = t1.proponent,
                  status = t171.status_desc,
                  delivery_date = t1.delivery_date
              }).ToList();

// 存入全局变量
_fullDataSource = result.Cast<dynamic>().ToList();
dtg_Data.DataSource = _fullDataSource;
  1. 编写统一的过滤方法,在两个ComboBox的SelectedIndexChanged事件中调用即可:
private void ApplyGridFilter()
{
    string selectCat = cbx_category.Text.Trim();
    string selectInsp = cbx_inspector.Text.Trim();

    IEnumerable<dynamic> filtered = _fullDataSource;

    if (selectCat != "Category")
    {
        filtered = filtered.Where(r => r.category != null && r.category.ToString().Trim() == selectCat);
    }

    if (selectInsp != "Inspector")
    {
        filtered = filtered.Where(r => r.inspected_by != null && r.inspected_by.ToString().Trim() == selectInsp);
    }

    dtg_Data.DataSource = filtered.ToList();
}

提示:如果后续需要扩展更多筛选条件,直接在ApplyGridFilter方法中追加判断逻辑即可,维护成本远低于操作DataGridView行的方案。

内容的提问来源于stack exchange,提问作者Raibyfe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:06:24