D365 FO中查找字段选值后显示关联名称且不存至数据库的方案
实现D365 FO查找控件显示关联名称但存储ID的方案
核心思路
通过自定义查找逻辑+控件显示文本重写,让单个查找控件在选中ID后自动显示关联表的名称,同时数据库仅存储原始ID,无需额外添加显示字段。该方案可通过通用化处理适配多关联表场景。
方案一:重写查找控件的Lookup与DisplayText方法(代码实现)
1. 重写查找控件的Lookup方法
在表单中reportToPosition控件的Lookup事件中,构建包含ID和名称的查找窗口,让用户直观选择:
public void lookup() { SysTableLookup sysTableLookup; Query query; QueryBuildDataSource qbds; // 初始化查找对象,绑定主表字段 sysTableLookup = SysTableLookup::newParameters(tableNum(MainTable), this); // 设置返回值为ID字段,同时显示名称字段 sysTableLookup.addLookupField(fieldNum(RoleTable, RoleCode), true); sysTableLookup.addLookupField(fieldNum(RoleTable, Title)); // 构建关联表查询 query = new Query(); qbds = query.addDataSource(tableNum(RoleTable)); // 可按需添加过滤条件,比如只显示有效角色 // qbds.addRange(fieldNum(RoleTable, Active)).value(queryValue(true)); sysTableLookup.parmQuery(query); sysTableLookup.performFormLookup(); }
2. 重写控件的DisplayText方法
让控件显示时自动从关联表拉取名称,而非原始ID:
public str displayText() { RoleTable roleTable; MainTable mainTable; str displayName = ''; mainTable = this.dataSource().cursor(); if (mainTable.reportToPosition != '') { select firstonly Title from roleTable where roleTable.RoleCode == mainTable.reportToPosition; displayName = roleTable.Title ?: mainTable.reportToPosition; } else { displayName = super(); } return displayName; }
3. 通用化适配多表场景
如果需要适配多个不同关联表,可封装通用工具类复用逻辑:
class CommonLookupHelper { // 通用查找构建方法 public static void performLookup(FormStringControl _control, TableId _relatedTableId, FieldId _relatedKeyField, FieldId _displayField) { SysTableLookup sysTableLookup; Query query; QueryBuildDataSource qbds; sysTableLookup = SysTableLookup::newParameters(_control.dataSource().table(), _control); sysTableLookup.addLookupField(_relatedKeyField, true); sysTableLookup.addLookupField(_displayField); query = new Query(); qbds = query.addDataSource(_relatedTableId); sysTableLookup.parmQuery(query); sysTableLookup.performFormLookup(); } // 通用显示文本获取方法 public static str getDisplayText(Common _mainRecord, FieldId _mainKeyField, TableId _relatedTableId, FieldId _relatedKeyField, FieldId _displayField) { Common relatedRecord; str mainKeyValue = _mainRecord.(_mainKeyField); str displayText = ''; if (mainKeyValue != '') { relatedRecord = tableBuffer(_relatedTableId); select firstonly (_displayField) from relatedRecord where relatedRecord.(_relatedKeyField) == mainKeyValue; displayText = relatedRecord.(_displayField) ?: mainKeyValue; } return displayText; } }
调用示例:
// Lookup方法中 public void lookup() { CommonLookupHelper::performLookup(this, tableNum(RoleTable), fieldNum(RoleTable, RoleCode), fieldNum(RoleTable, Title)); } // DisplayText方法中 public str displayText() { MainTable mainTable = this.dataSource().cursor(); return CommonLookupHelper::getDisplayText(mainTable, fieldNum(MainTable, reportToPosition), tableNum(RoleTable), fieldNum(RoleTable, RoleCode), fieldNum(RoleTable, Title)); }
方案二:无代码配置(表单设计器实现)
适用于关联关系简单的场景:
- 打开表单设计器,选中
reportToPosition控件; - 在属性窗口找到ReplaceField,设置为关联表的显示字段(如
RoleTable.Title); - 确保控件的DataSource和DataField绑定主表的
reportToPosition字段; - 测试验证:选中ID后控件自动显示关联名称,数据库仍存储原始ID。
注意:复杂过滤或多表关联场景建议用方案一。
验证要点
- 选中查找值后,控件显示关联名称而非ID;
- 保存记录后,数据库
reportToPosition字段存储原始ID; - 编辑已有记录时,控件自动加载对应关联名称;
- 空值或无匹配关联记录时,控件显示原始ID或空值。
内容的提问来源于stack exchange,提问作者user4833581
相关产品推荐
相关产品推荐

