Presentation Rule是Tree的展示规则,其通过简单的配置文件定义Tree的各级节点。本文档以Item Type的需求为例,讲解如何配置自定义的Presentation Rule。


关于Item Type:

itemType实际上是对element的数据格式包装。你可以在其中定义任何类型的字段:ID、类型、材质、每单位的预算。其创建的是一个数据对象。

再通过attach操作将Element与数据对象连接起来,我们就能轻易的对多个同类的Element附加上共同属性。

在Report功能中可以将这些对象的数据整理成报表,并且可以定义表的列、格式化、排序方式等。

参阅:https://communities.bentley.com/communities/other_communities/chinafirst/w/chinawiki/42951/page


准备工作:

ItemType.PresentationRuleSet.json

{
  "$schema": "../../node_modules/@bentley/presentation-common/Ruleset.schema.json",
  "id": "ItemType",
  "rules": [
    {
      "ruleType": "RootNodes",
      "specifications": [
        {
          "specType": "InstanceNodesOfSpecificClasses",
          "classes": {
            "schemaName": "ECDbMeta",
            "classNames": [
              "ECClassDef"
            ]
          },
          "relatedInstances": [
            {
              "relationshipPath": {
                "relationship": {
                  "schemaName": "ECDbMeta",
                  "className": "SchemaOwnsClasses"
                },
                "direction": "Backward"
              },
              "isRequired": true,
              "alias": "schema"
            }
          ],
          "instanceFilter": "schema.Name ~ \"%CustomItemTypes%\" AND this.Name ~ \"%Aspect%\"",
          "groupByClass": false,
          "groupByLabel": false
        }
      ]
    },
    {
      "ruleType": "ChildNodes",
      "condition": "ParentNode.IsOfClass(\"ECClassDef\", \"ECDbMeta\")",
      "specifications": [
        {
          "specType": "InstanceNodesOfSpecificClasses",
          "classes": {
            "schemaName": "BisCore",
            "classNames": [
              "Element"
            ]
          },
          "arePolymorphic": true,
          "relatedInstances": [
            {
              "relationshipPath": {
                "relationship": {
                  "schemaName": "BisCore",
                  "className": "ElementOwnsUniqueAspect"
                },
                "direction": "Forward"
              },
              "isRequired": false,
              "alias": "uniqueAspect"
            },
            {
              "relationshipPath": {
                "relationship": {
                  "schemaName": "BisCore",
                  "className": "ElementOwnsMultiAspects"
                },
                "direction": "Forward"
              },
              "isRequired": false,
              "alias": "multiAspect"
            }
          ],
          "instanceFilter": "uniqueAspect.ECClassId = parent.ECInstanceId OR multiAspect.ECClassId = parent.ECInstanceId",
          "groupByClass": false,
          "groupByLabel": false
        }
      ]
    },
    {
      "ruleType": "Content",
      "specifications": [
        {
          "specType": "SelectedNodeInstances"
        }
      ]
    },
    {
      "ruleType": "InstanceLabelOverride",
      "class": {
        "schemaName": "ECDbMeta",
        "className": "ECClassDef"
      },
      "values": [
        {
          "specType": "Property",
          "propertyName": "DisplayLabel"
        },
        {
          "specType": "Property",
          "propertyName": "Name"
        }
      ]
    }
  ]
}

使用方法:

将该文件放入对应目录下,使用时直接在TreeWidge中传入id即可。例如:

<TreeWidget
   imodel={imodel}
   rulesetId="ItemType"
/>

代码分析:

"$schema": "../../node_modules/@bentley/presentation-common/Ruleset.schema.json",
"id": "ItemType",

先配置编写json时的规则,配置后带有编写提示。接着定义此Presentation的Id。

"rules": [
    {
      "ruleType": "RootNodes",
      "specifications": [
        {
          "specType": "InstanceNodesOfSpecificClasses",
          "classes": {
            "schemaName": "ECDbMeta",
            "classNames": [
              "ECClassDef"
            ]
          },
         ...
        }
      ]
    },
    ...
]

定义节点类型为(树的根节点)和节点规则(来自于某个表的实例)。

ItemType在schema中的存储方式如下图:(该图来自iModelconsole-schema explorer)

其中Doors、Escalator、Fencing为在该文件中用户已关联Element的ItemType。

所以树的根节点应为Class,查询: SELECT * FROM ECDbMeta.ECClassDef。

此查询语句会找出所有的class,而我们仅需要其中的三个,为此要对其进行筛选。

"relatedInstances": [
  {
    "relationshipPath": {
      "relationship": {
        "schemaName": "ECDbMeta",
        "className": "SchemaOwnsClasses"
      },
      "direction": "Backward"
    },
    "isRequired": true,
    "alias": "schema"
  }
],
"instanceFilter": "schema.Name ~ \"%CustomItemTypes%\" AND this.Name ~ \"%Aspect%\"",

首先引入相关实例relatedInstances,该实例与节点的关系relationshipPath是ECDbMeta.SchemaOwnsClasses这个关系表定义的。

在schema explorer中我们可以查看这个关系表。

根据关系图可知,一个Schema可能包含0-n个class。他们是1对0~n的关系,也就是说Class必定有自己的Schema。

这里Schema是Source(内容),Class是Target(目标)。我们通过Class去找Schema,所以方向就是Backward(反向)。找到的Schema我们将其命名(alias)为schema。此别名可以在后续的筛选条件中使用。

回过头看,这里为什么要引入Schema和Class的关系?

因为所有有关ItemType的class,他们所属的schema都有一个特征,即schema的名字中包含‘CustomItemTypes’。

我们查询到所有的Class,筛选其所属schema名称中包含‘CustomItemTypes’的class,最终的结果就是ItemType相关的Class。

"instanceFilter": "schema.Name ~ \"%CustomItemTypes%\" AND this.Name ~ \"%Aspect%\""

这行定义筛选条件的代码中,schema变量是我们刚查询到的schema,this就是当前的节点class。代码含义为:筛选所属schema的name中包含‘CustomItemTypes’的,且自身name包含‘Aspect’的Class。

ps.如果只有第一个筛选条件,筛选的结果是所有的ItemType,加上第二个条件后,仅筛选已经被attach到element的ItemType。

接着定义子节点及子节点的规则:

"ruleType": "ChildNodes",
"condition": "ParentNode.IsOfClass(\"ECClassDef\", \"ECDbMeta\")",

子节点应为Element,所以查询语句如下:

"specType": "InstanceNodesOfSpecificClasses",
"classes": {
  "schemaName": "BisCore",
  "classNames": [
    "Element"
  ]
},

引入关系实例的代码不再赘述:

"relatedInstances": [
  {
    "relationshipPath": {
      "relationship": {
        "schemaName": "BisCore",
        "className": "ElementOwnsUniqueAspect"
      },
      "direction": "Forward"
    },
    "isRequired": false,
    "alias": "uniqueAspect"
  },
  {
    "relationshipPath": {
      "relationship": {
        "schemaName": "BisCore",
        "className": "ElementOwnsMultiAspects"
      },
      "direction": "Forward"
    },
    "isRequired": false,
    "alias": "multiAspect"
  }
],

筛选条件为:

"instanceFilter": "uniqueAspect.ECClassId = parent.ECInstanceId OR multiAspect.ECClassId = parent.ECInstanceId"

这里的Target就是我们在之前提到过Schema中ItemType存储的表。依照此关系图查找出的其实是Class。

筛选条件的含义为,在所有的Element中筛选其拥有的uniqueAspect(或者multiAspect)刚好是父节点(class)的Element。

这样就完成了对Element按ItemTypeClass进行分类的功能。

最后对节点进行重命名:

{
  "ruleType": "InstanceLabelOverride",
  "class": {
    "schemaName": "ECDbMeta",
    "className": "ECClassDef"
  },
  "values": [
    {
      "specType": "Property",
      "propertyName": "DisplayLabel"
    },
    {
      "specType": "Property",
      "propertyName": "Name"
    }
  ]
}

含义为,重命名Class节点。先展示DisplayLabel属性,如果没有就展示Name属性。


效果展示:

results matching ""

    No results matching ""