如何在Enterprise Architect外接程序中获取图中选中元素
问题描述
我目前正在开发具备多项功能的EA Add-In插件,其中一项功能为实现图内端口的水平对齐。
为此,我需要获取图中当前选中的元素/端口(本场景中为Hand(Port4))作为锚点元素,使其余选中端口对齐至相同x坐标。
当前操作的示例图如下:
在EA原生环境中,使用如下SQL语句可正常运行:
Select Object_ID, Name from t_object where Object_id = #CurrentElementID#
我在Visual Studio 2022环境下使用C#开发该Add-In时,原本计划通过SQLQuery方法执行同类查询,代码如下:
String selectedPort = repository.SQLQuery("Select Object_ID, Name from t_object where Object_ID = #CurrentElementID# ");
代码执行时在Object_ID = #CurrentElementID#位置抛出语法错误,暂未定位问题原因。尝试替换为#OBJECTID#参数后同样无法正常运行,需要找到可行方案获取port.top属性值,实现其余端口与锚点端口的对齐。
解决方案
报错核心原因
#CurrentElementID#、#OBJECTID#这类带#包裹的宏占位符,仅能在EA原生的搜索、模板、内置脚本环境中被EA引擎自动解析替换。通过Add-In调用Repository.SQLQuery()方法时,EA不会对传入的SQL语句做任何宏替换,会直接把带#xxx#的原始语句传给底层数据库执行,自然会触发SQL语法错误。
实现步骤
完全不需要绕路写SQL查询,直接调用EA自动化接口的选中集能力即可拿到准确的端口位置数据,实现逻辑更稳定,还能避免数据库和内存数据不同步的问题:
- 第一步:获取当前激活图的选中对象集合
调用Repository.GetCurrentDiagram()拿到当前打开的图对象,读取其SelectedObjects集合,该集合存储了当前用户在图内选中的所有元素、端口、连接的实例引用。 - 第二步:筛选选中的端口,确定对齐锚点
遍历SelectedObjects集合时,先通过ElementID拿到对应的元素对象,判断元素Type属性是否为"Port"即可筛选出所有选中端口,取第一个符合条件的端口作为水平对齐的锚点即可。 - 第三步:修改其余端口坐标,刷新界面生效
图上元素的渲染坐标直接存储在DiagramObject实例上,直接读取锚点的Left属性作为对齐目标X坐标,遍历其余选中端口,将其Left属性修改为目标值,同步调整Right属性保持端口原有宽度,最后刷新图即可看到对齐效果。
核心参考代码
// 获取当前激活的图 EA.Diagram currentDiag = repository.GetCurrentDiagram(); if (currentDiag == null) return; EA.DiagramObject anchorPort = null; // 遍历选中项,找到第一个端口作为锚点 foreach (EA.DiagramObject selectedObj in currentDiag.SelectedObjects) { EA.Element ele = repository.GetElementByID(selectedObj.ElementID); if (ele != null && ele.Type == "Port") { anchorPort = selectedObj; break; } } if (anchorPort == null) return; int targetX = anchorPort.Left; // 遍历其余选中端口,修改X坐标实现水平对齐 foreach (EA.DiagramObject selectedObj in currentDiag.SelectedObjects) { EA.Element ele = repository.GetElementByID(selectedObj.ElementID); if (ele != null && ele.Type == "Port" && selectedObj.DiagramObjectID != anchorPort.DiagramObjectID) { int portWidth = selectedObj.Right - selectedObj.Left; selectedObj.Left = targetX; selectedObj.Right = targetX + portWidth; selectedObj.Update(); } } // 提交修改并刷新图界面 currentDiag.Update(); repository.SaveDiagram(currentDiag.DiagramID); repository.ReloadDiagram(currentDiag.DiagramID);
补充说明:如果确实需要通过SQL查询元素数据,不要使用宏占位符,直接将已经拿到的元素ID拼接到SQL语句中即可,注意做好参数校验避免SQL注入风险。
内容的提问来源于stack exchange,提问作者Ivan Mijatovic
相关产品推荐
相关产品推荐

