☰
错误面板可优化清单记录
2026/10/11 2:44:01 网站建设 项目流程

代码阅读总结

这是中望CAD插件里质检结果展示的 UserControl(QCResultUserControl),基于WinForm,核心功能:

  1. 两个构造:无参构造用于插件启动预创建控件;带dwg路径构造直接加载图纸质检数据
  2. UI:顶部2个筛选下拉框(检查项 / 错误级别)、刷新、清空按钮;中间DGV表格展示质检记录;底部状态栏统计数量
  3. 数据逻辑:QCResultDB读取当前图纸质检记录;筛选后用BindingList绑定DGV;修改【级别】ComboBox单元格时自动写库更新
  4. 交互:
    • 双击行:根据句柄在CAD里选中实体 + 缩放定位
    • Ctrl+鼠标滚轮:缩放行高+列宽
    • 单元格着色:Error红色、Warning黄褐色、Info钢蓝色
  5. 数据库操作:LoadAll、UpdateLevel、Clear清空整张图纸质检记录

现有已知小隐患(顺带提一句)

  • DgvResult_MouseWheel强制同步所有列宽一起增减,用户单独手动调某一列宽度后,按Ctrl滚轮会覆盖掉手动宽度;
  • _allData是内存全量数据,ApplyFilter只是内存筛选,不会二次读库;
  • 句柄解析只支持16进制long,部分极端句柄场景需要容错;

你想要新增什么功能?给你几个可选方向,或者你直接描述需求:

可选功能清单,你挑一个,或者自定义:

  1. ✅增加导出功能:【导出Excel】按钮,把当前筛选后的质检记录导出csv/xlsx
  2. ✅增加删除单行记录:每行增加删除按钮,只删除选中这一条质检结果(不是全部清空)
  3. ✅增加右键菜单:右键行 → 定位实体 / 删除本条记录 / 复制句柄 / 复制错误信息
  4. ✅增加批量修改级别:多选行,批量把选中行修改成Info/Warning/Error
  5. ✅增加高亮实体持久化:选中DGV行时,CAD实时选中对应实体(不需要双击)
  6. ✅增加过滤隐藏已修复项:增加【已修复】标记字段,增加复选框筛选已修复/未修复
  7. ✅增加统计饼图:在状态栏上方展示各级别数量统计(Error几条、Warning几条)
  8. ✅增加复制句柄按钮:选中行一键复制实体句柄到剪贴板
  9. ✅增加查找框:文本搜索框,模糊搜索错误描述、图层、检查项
  10. ✅保存用户列宽布局:退出控件时保存DGV各列宽度,下次打开自动恢复

你直接告诉我:

例如:选第3个,增加右键菜单,包含定位实体、复制句柄、删除本条记录
或者你写自己想要的功能描述。





需求说明

新增按钮:选中,放在【刷新】、【清空记录】后面。
功能:点击按钮 → 将当前筛选后表格里所有行对应的实体句柄一次性在CAD里选中(批量选中)。

注意:只处理当前筛选可见列表,不是_allData全部数据;跳过句柄为空、实体已删除的记录。

一、需要修改/新增代码位置

1. BuildUI 面板顶部,添加按钮(在 btnClear 后面)

找到 BuildUI 里面var btnClear = new Button...那一段,新增btnSelectFiltered:

var btnSelectFiltered = new Button { Text = "选中", Left = 620, Top = 2, Width = 70, Height = 28 }; btnSelectFiltered.Click += BtnSelectFiltered_Click;

然后修改panelTop.Controls.AddRange,把这个按钮加进去:

panelTop.Controls.AddRange(new Control[] { lblCheck, _cboCheckItemFilter, lblLevel, _cboLevelFilter, btnRefresh, btnClear, btnSelectFiltered });

注意坐标:btnClear Left=545,宽度70 → btnClear 右边界 545+70=615,所以Left=620刚好放在后面;如果控件总宽度不够,可适当放大UserControl宽度,或者调整所有按钮X坐标。

2. 新增按钮点击事件BtnSelectFiltered_Click

private void BtnSelectFiltered_Click(object sender, EventArgs e) { if (_dgvResult.DataSource is not BindingList<QCErrorResult> filteredList) return; Document doc = ZwSoft.ZwCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; if (doc == null) { MessageBox.Show("没有激活的CAD文档!"); return; } Database db = doc.Database; Editor ed = doc.Editor; List<ObjectId> selectIds = new List<ObjectId>(); int invalidCount = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (var item in filteredList) { if (string.IsNullOrWhiteSpace(item.Handle)) { invalidCount++; continue; } try { long hVal = long.Parse(item.Handle, NumberStyles.HexNumber); Handle h = new Handle(hVal); ObjectId oid = db.GetObjectId(false, h, 0); if (oid.IsNull || !oid.IsValid) { invalidCount++; continue; } // 尝试打开实体校验是否存在 Entity ent = tr.GetObject(oid, OpenMode.ForRead) as Entity; if (ent != null) { selectIds.Add(oid); } else { invalidCount++; } } catch { invalidCount++; } } tr.Commit(); } // 交给CAD选中 ed.SetImpliedSelection(selectIds.ToArray()); string msg = $"批量选中:{selectIds.Count} 个实体"; if (invalidCount > 0) msg += $",{invalidCount}条记录实体已失效"; _lblStatus.Text = msg; ed.WriteMessage($"\n{msg}"); }

3. 补充:命名空间(如果缺少)

using System.Collections.Generic; using ZwSoft.ZwCAD.DatabaseServices; using ZwSoft.ZwCAD.EditorInput; using ZwSoft.ZwCAD.ApplicationServices;

二、完整替换 BuildUI 顶部panel代码段(直接替换你原代码)

//顶部筛选栏 Panel panelTop = new Panel(); panelTop.Dock = DockStyle.Fill; var lblCheck = new Label { Text = "检查项:", Left = 6, Top = 8, AutoSize = true }; _cboCheckItemFilter = new ComboBox { Left = 60, Top = 4, Width = 180, DropDownStyle = ComboBoxStyle.DropDownList }; _cboCheckItemFilter.SelectedIndexChanged += (s, e) => ApplyFilter(); var lblLevel = new Label { Text = "错误级别:", Left = 260, Top = 8, AutoSize = true }; _cboLevelFilter = new ComboBox { Left = 330, Top = 4, Width = 120, DropDownStyle = ComboBoxStyle.DropDownList }; _cboLevelFilter.SelectedIndexChanged += (s, e) => ApplyFilter(); var btnRefresh = new Button { Text = "刷新", Left = 470, Top = 2, Width = 70, Height = 28 }; btnRefresh.Click += (s, e) => LoadResultData(); var btnClear = new Button { Text = "清空记录", Left = 545, Top = 2, Width = 70, Height = 28 }; btnClear.Click += BtnClear_Click; //=====新增选中按钮===== var btnSelectFiltered = new Button { Text = "选中", Left = 620, Top = 2, Width = 70, Height = 28 }; btnSelectFiltered.Click += BtnSelectFiltered_Click; panelTop.Controls.AddRange(new Control[] { lblCheck, _cboCheckItemFilter, lblLevel, _cboLevelFilter, btnRefresh, btnClear, btnSelectFiltered });

三、重要注意点

  1. 数据源类型:_dgvResult.DataSource是BindingList<QCErrorResult>,正好就是当前筛选后的数据集,完美符合需求,不会把全部数据选中。
  2. 事务:所有GetObject都放在同一个Transaction,性能更好,避免多次打开事务。
  3. 异常容错:句柄解析失败、实体已删除、ObjectId无效都会计入无效数量,状态栏提示。
  4. 界面宽度问题:原UserControl大小600,360,现在按钮放到620位置,宽度不够。建议把构造BuildUI里
this.Size = new Size(600, 360);

改成

this.Size = new Size(700, 360);
  1. 边界场景:
    • 筛选结果为空:点击选中,状态栏提示选中0个实体
    • 多个筛选条件组合,只选中当前筛选结果
    • 多个实体跨图层,一次性CAD预选

四、可选增强(如果你需要)

可选:选中之后自动Zoom到所有选中实体的范围(框选缩放),需要我追加这段代码到BtnSelectFiltered_Click末尾吗?

或者,保持现在只选中不缩放?




if (!(_dgvResult.DataSource is BindingList<QCErrorResult> filteredList))

完整那一行:

if (!(_dgvResult.DataSource is BindingList<QCErrorResult> filteredList))

说明:C#7.3 不支持is not模式匹配,但是支持is带变量声明,外层套!()取反即可,只改这一行,逻辑完全不变。

如果你想,我顺便把 BtnSelectFiltered_Click 完整替换成兼容 C#7.3 的版本。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询