资讯动态

UG(NX)二次开发 BlockUI 集列表实战技巧与回调函数详解

发布时间:2026/9/15 23:38:40 来源:尧图企业网站定制
1. BlockUI集列表控件基础入门在UG/NX二次开发中BlockUI集列表SetList是个非常实用的控件但很多开发者对它了解不多。我第一次接触这个控件时也踩了不少坑后来发现它特别适合需要动态增减条目的交互场景。比如做批量面操作、多组参数输入等功能时用集列表比普通控件方便得多。集列表的核心特点是能通过种子块SeedDlxFile动态生成UI元素。想象一下乐高积木种子块就是基础模块点击添加按钮就能复制出多个相同结构的UI组。每个新增的条目都包含完整的交互元素比如选择器、输入框等这在处理可变数量参数时特别有用。与树列表TreeList相比集列表更适合线性排列的简单数据结构。树列表适合展示层级关系而集列表更擅长处理平级的、可动态增减的条目集合。实际项目中我常用集列表做这些场景多组几何体选择比如批量面操作可变参数的阵列设置需要用户动态添加/删除的条目管理2. 回调函数配置与实战技巧2.1 初始化设置要让集列表正常工作首先要在对话框设计器里配置几个关键属性// 设置列标题和宽度 list0.ColumnLabels new string[] { 序号, 类型, 状态 }; list0.ColumnWidths new int[] { 80, 150, 200 }; // 指定种子块文件必须提前设计好 list0.SeedDlxFile D:\templates\set_template.dlx; // 启用添加/删除功能 list0.ShowAddNewSet true; list0.ShowRemove true;这里有个容易踩坑的地方种子块文件路径要用绝对路径相对路径经常找不到文件。我建议把模板文件放在固定目录或者通过API获取NX安装目录下的标准路径。2.2 回调函数绑定集列表的核心交互靠回调函数实现主要有三种回调需要处理// 添加回调 list0.SetAddHandler(new NXOpen.BlockStyler.SetList.AddCallback(AddCallback)); // 删除回调 list0.SetDeleteHandler(new NXOpen.BlockStyler.SetList.DeleteCallback(DeleteCallback)); // 选择变化回调可选 list0.SetOnSelectHandler(new NXOpen.BlockStyler.SetList.OnSelectCallback(SelectCallback));添加回调的典型实现如下static int itemCount 1; // 全局计数器 int AddCallback(SetList setList) { // 添加新条目并获取其UI块 UIBlock newBlock list0.AddNewSet(true); // 设置各列显示文本 list0.SetItemText(newBlock, new string[] { itemCount.ToString(), 类型 itemCount, DateTime.Now.ToString(HH:mm:ss) }); itemCount; return 0; // 返回0表示成功 }3. 动态数据管理实战3.1 条目删除处理删除操作比添加复杂些因为要处理多选情况。这里分享我的优化版删除回调int DeleteCallback(SetList list, UIBlock blockToDelete) { // 获取所有选中项支持Ctrl多选 UIBlock[] selectedItems list0.GetSelected(); if (selectedItems.Length 0 blockToDelete ! null) { // 处理通过删除按钮触发的情况 list0.Delete(blockToDelete); } else { // 处理多选删除 foreach (UIBlock item in selectedItems) { // 先检查是否有效再删除 if (list0.GetItems().Contains(item)) list0.Delete(item); } } // 重新编号 ReindexItems(); return 0; } void ReindexItems() { UIBlock[] allItems list0.GetItems(); for (int i 0; i allItems.Length; i) { string[] texts list0.GetItemText(allItems[i]); texts[0] (i 1).ToString(); // 更新序号列 list0.SetItemText(allItems[i], texts); } }3.2 数据获取与处理点击确定/应用按钮时需要遍历集列表获取用户输入。这里有个类型转换的坑要注意public int GetSetListData() { ListMyData result new ListMyData(); foreach (UIBlock block in list0.GetItems()) { // 必须转换为CompositeBlock CompositeBlock compBlock (CompositeBlock)block; // 获取种子块中的各个控件 BlockStyler.UIBlock[] subBlocks compBlock.GetBlocks(); // 假设第一个是面选择器 FaceCollector faceSelector (FaceCollector)subBlocks[0]; // 假设第二个是整数输入 IntegerBlock intInput (IntegerBlock)subBlocks[1]; result.Add(new MyData { Faces faceSelector.GetSelectedObjects(), Value intInput.Value }); } return result; }4. 高级技巧与性能优化4.1 批量操作优化当处理大量条目时直接操作UI会很慢。我的经验是开始批量操作前调用theUI.BeginUpdate()操作结束后调用theUI.EndUpdate()中间过程不刷新UI// 批量添加100个条目 theUI.BeginUpdate(); try { for (int i 0; i 100; i) { AddCallback(list0); } } finally { theUI.EndUpdate(); // 确保始终执行 }4.2 自定义排序实现集列表本身不支持排序但我们可以通过代码实现。这里分享我的排序方法void SortItems(int columnIndex, bool ascending) { var items list0.GetItems().ToList(); items.Sort((a, b) { string textA list0.GetItemText(a)[columnIndex]; string textB list0.GetItemText(b)[columnIndex]; // 尝试数值比较 if (int.TryParse(textA, out int numA) int.TryParse(textB, out int numB)) return ascending ? numA.CompareTo(numB) : numB.CompareTo(numA); // 默认字符串比较 return ascending ? textA.CompareTo(textB) : textB.CompareTo(textA); }); // 清空后重新添加保持UI状态 var expandedStates SaveExpandedStates(); list0.Clear(); foreach (var item in items) { list0.AddExistingSet(item, true); } RestoreExpandedStates(expandedStates); }4.3 状态保持技巧在对话框重新打开时我常用这些方法保持集列表状态将数据序列化为XML或JSON使用NX的Preferences机制存储对于几何体选择存储Tag后再恢复// 保存当前状态 string SaveSetListState() { var state new ListDictionarystring, string(); foreach (UIBlock block in list0.GetItems()) { var itemState new Dictionarystring, string(); CompositeBlock compBlock (CompositeBlock)block; // 保存文本 itemState[Texts] string.Join(|, list0.GetItemText(block)); // 保存子控件值 foreach (var subBlock in compBlock.GetBlocks()) { if (subBlock is IntegerBlock intBlock) itemState[intBlock.BlockID] intBlock.Value.ToString(); // 其他类型处理... } state.Add(itemState); } return JsonConvert.SerializeObject(state); } // 加载状态 void LoadSetListState(string json) { var state JsonConvert.DeserializeObjectListDictionarystring, string(json); list0.Clear(); foreach (var itemState in state) { UIBlock newBlock list0.AddNewSet(false); // 恢复文本 string[] texts itemState[Texts].Split(|); list0.SetItemText(newBlock, texts); // 恢复子控件值 CompositeBlock compBlock (CompositeBlock)newBlock; foreach (var subBlock in compBlock.GetBlocks()) { if (subBlock is IntegerBlock intBlock itemState.ContainsKey(intBlock.BlockID)) intBlock.Value int.Parse(itemState[intBlock.BlockID]); // 其他类型处理... } } }在实际项目中我发现合理使用集列表可以大幅提升用户体验。特别是在处理数量不定的参数组时比静态UI灵活得多。不过要注意控制条目数量超过50条建议改用其他展示方式。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价