第七期视频回放
第七期代码及课件下载地址
第七期直播内容文字版
工程属性概念介绍
引言
对于工程信息,主要分为几何数据与工程数据两个部分,对于几何数据,Bentley采用模型来表达,而工程数据,起初Bentley采用XAttribute的方式在dgn文件中开辟一个特定空间存储非几何数据,但是在由于没有统一数据存储的方式和格式,导致不同专业软件之间的信息无法交流。最后,Bentley经过大量的摸索和借鉴形成了一套系统的数据解决方案系统ECFramework (Engineering Content Framework ),通过这套方案Bentley真正实现各个专业软件之间数据的无损流动和互动。<br />![Slide2.JPG](https://cdn.nlark.com/yuque/0/2022/jpeg/21640708/1646273159874-ea4c1e9f-df7f-450f-a1b5-2a588b6b06a4.jpeg#clientId=ud504987d-c407-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=u303d2bdd&margin=%5Bobject%20Object%5D&name=Slide2.JPG&originHeight=720&originWidth=1280&originalType=binary&ratio=1&rotation=0&showTitle=false&size=65580&status=done&style=none&taskId=ude514288-1edc-4a7e-a8f1-ecb462b54ef&title=)<br />**图1 工程属性主要内容一览**<br /> 不同于应用程序框架,作为解决方案框架,整个ECFrameWork包含以下几个部分:
- ECObjects 和ECXML: 用来定义工程内容
- ECServices: 为多种数据来源的工程环境提供的一套统一的服务
- ECControls:EngineeringContentBrowser , PropertyPane等控件
ECClassEditor:外部编辑ECSchema的编辑器
相较于使用EC框架以前,架构如图所示:
图2 无EC框架时数据交换方法
图3 使用EC框架数据交换方法
使用EC框架后,所有的工程信息被统一为相同的格式,单个应用程序生成的信息可被整个解决方案中使用,大大提高了信息的利用价值。EC属性概念简述
ECObjects
ECObject(Engineering Content Object),即工程内容对象,用于描述工程中的数据。笼统地说,它相当于一个表格文件,与表格中的数据行,我们可以使用编程的方法对表格中的内容进行定义,修改,查询和更新。
图4 ECObjectECSchema
ECSchema是描述数据的数据,用于表达EC的数据结构。简单的来说,ECSchema是一种用于表达ECObjects信息的载体,他可独立存在,其他任何程序只要遵循其构建标准都可获取我们所定义的工程信息,扩展性强。您可以采用创建Xml文件直接编写的方法或使用ClassEditor工具创建Schema文件。
<?xml version="1.0" encoding="utf-8" ?>
<ECSchema schemaName="ComplexSchema" nameSpacePrefix="ComplexSchema" version="1.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
<ECClass typeName="Contact" isStruct="True" isDomainClass="False">
<ECProperty propertyName="Name" typeName="string" /> "
<ECProperty propertyName="Age" typeName="int" /> "
<ECArrayProperty propertyName="PhoneNumber" typeName="string" /> "
</ECClass>
<ECClass typeName="StructClass" isStruct="True" isDomainClass="False">
<ECProperty propertyName="StringProperty" typeName="string" /> "
<ECProperty propertyName="IntProperty" typeName="int" /> "
<ECArrayProperty propertyName="ArrayProperty" typeName="string" minOccurs="1" maxOccurs="1" /> "
<ECArrayProperty propertyName="ContactData" typeName="Contact" isStruct="True" /> "
</ECClass>
<ECClass typeName="ComplexClass" isDomainClass="True">
<ECProperty propertyName="IntProperty" typeName="int" />"
<ECProperty propertyName="StringProperty" typeName="string" /> "
<ECProperty propertyName="DoubleProperty" typeName="double" /> "
<ECProperty propertyName="DateTimeProperty" typeName="dateTime" />"
<ECProperty propertyName="BooleanProperty" typeName="boolean" />"
<ECProperty propertyName="APoint2d" typeName="point2d" />"
<ECProperty propertyName="APoint3d" typeName="point3d" />"
<ECProperty propertyName="ALong" typeName="long" />"
<ECProperty propertyName="ABinary" typeName="binary" />"
<ECArrayProperty propertyName="SimpleArrayProperty" typeName="string"/>"
<ECArrayProperty propertyName="FixedArrayProperty" typeName="string" minOccurs="1" maxOccurs="1" />"
<ECArrayProperty propertyName="StructArrayProperty" typeName="StructClass" isStruct="True" />"
<ECArrayProperty propertyName="FixedStructArrayProperty" typeName="StructClass" minOccurs="1" maxOccurs="1" isStruct="True" />"
<ECStructProperty propertyName="StructProperty" typeName="StructClass" />"
</ECClass>"
</ECSchema>
如果您拥有读写Xml文件经验的话,相信您对其肯定不会陌生,因为从文件后缀(*.xml)可以看出,Schema文件也遵循Xml文件的构建标准。如果您没有相关经验,也没有关系,以下为阅读该文件的方法:
Xml文件有点类似于树状图表或者多项式,首先遵循的标准就是开始与结束的符号需要对应。即<…/>或<>…</>对应于(…),可以使用VisualStudio创建Xml文件的方法,使用程序辅助编写Schema文件,如果尖括号不对应程序会有警告显示
图5 错误警告信息
- 在一个ECSchema文件中可以囊括多个ECClass,而一个ECClass可以拥有多个ECProperty或ECArrayProperty,ECStructProperty。ECProperty表示的是常规类型的属性,包括int,string,double,datetime(日期),point2d,point3d(坐标),long,binary等;而ECStructProperty指的是自定义的结构体,具有由ECClass定义的复杂类型;而ECArrayProperty指的是动态链表,在其中我们可以添加多个该属性。
- ECClass可以继承其他的ECClass,用于表达工程属性中的层级关系。同时,其不仅可以使用当前Schema文件内部的定义,还可以使用外部Schema中的信息。
- ECPropertyValue表示ECInstance中单个ECProperty的值。在大多数情况下,ECPropertyValue组成一个ECInstance。ECPropertyValue保存由ECProperty定义的各种类型的数据
ECSchema,ECClass,ECProperty,ECInstance,ECPropertyValue间关系
图7 EC关系一览
他们之间的关系,对于EC框架,若您对数据库较为熟悉:
- ECRepository 就相当于整个数据库系统
- ECSchema 就相当于一个数据库的定义
- ECClass 就相当于一个数据库中表的定义
- ECProperty 就像是表结构中每一列的定义
- ECInstance 相当于每个表中的每一行。
- ECPropertyValue 就 相当于每一行中的每一个单元
- ECClass加上所产生的ECInstances 就相当于一个数据库所有的表格
如果您没有接触过数据库,我们就以工程中明细表作以类比:
- ECRepository 就相当于某某项目施工图项目阶段
- ECSchema 就相当于结构专业
- ECClass 就相当于结构柱明细表
- ECProperty 就相当于结构柱属性定义(钢筋型号,混凝土强度,混凝土保护层厚度)
- ECInstance 就相当于指定某个结构柱
- ECPropertyValue 就相当于该结构柱的属性值(如钢筋混凝土强度为C40,钢筋型号HRB400,混凝土保护层厚度取35)
ECClass加上所产生的ECInstances 就相当于该项目的柱明细表
ECRelationship
我们使用ECRelationship来表达不同工程数据类型之间的相互关系,它相当于第三方,关联了两个工程对象。ECRelationshipClass就像是在数据库中定义了一个链接表格,ECRelationshipInstance 就是这个表格中的一行。
图8 ECRelationship<?xml version="1.0" encoding="utf-8"?>
<ECSchema schemaName="Simple" nameSpacePrefix="demo" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
<ECClass typeName="Widget" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECClass typeName="Gadget1" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECClass typeName="Gadget2" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECRelationshipClass typeName="WidgetHasGadgets" description="WidgetHasGadgets" isDomainClass="True" strength="referencing" strengthDirection="forward">
<Source cardinality="(1,1)" roleLabel="has Gadgets" polymorphic="False">
<Class class="Widget" />
</Source>
<Target cardinality="(1,N)" roleLabel="are held by Widget" polymorphic="False">
<Class class="Gadget1" />
<Class class="Gadget2" />
</Target>
</ECRelationshipClass>
</ECSchema>
例如在该项目中,在ECRelationshipClass部分,Source中包含名为Widget的EC类,而Target中拥有名为Gadget1和Gadget2的EC类。通过代码给元素赋予EC实例,得到的结果见下图:
图9 ECRelationship导入结果ItemType概念简述
ItemType是基于EC计数开发更容易使用的功能,是EC的简化形式,它可以附加到元素,模型与文件中。ItemType作为特殊的ECClass,具有ECClass的部分功能。与Schema相比,ItemType具有以下特点:
不支持继承
- 为每个基元属性提供默认值
- 不支持自定义属性
- 仅支持部分属性类型
具有ItemType工具,使用更加便捷
对于从未接触过工程属性概念的用户来说,这里笔者强烈建议您首先学习ItemType的使用方法,因为其具有图形界面工具,可以更直观的对工程属性进行表达,同时ItemType更加简单,容易上手。
图10 ItemType
图11 ItemTypeCustomProperty
将ItemType附加到主机以生成项(Item)时,每个CustomProperty成为项(Item)中的属性值。它的名称具有唯一性,这个名称也是是用户所看到的名称,同时内部会创建一个用户看不到的内部名称与ID,它支持integer、boolean或string等类型。同时可设置彼此的优先级以控制属性在界面上的显示顺序,创建时他会给出一个默认值。
ItemType
ItemType是定义CustomProperties的命名集合,可以将其附加到元素、模型和文件上。在此过程中就产生了一个“项”(Item),其中每个ItemType的CustomProperty定义都成为一个属性,项中的每个值都将根据对应的CustomProperty设置的默认值进行初始化。
ItemTypeLibrary
ItemTypeLibrary是定义ItemTypes和CustomPropertyTypes的命名集合。注意,文件中的库名称不可重名。
工程属性操作方法
EC属性操作方法
因为Schema文件导入后没有像ItemType的操作界面,因此若需要了解文件中ECSchema的导入情况,需要使用keyin命令:ecx schema list显示在提示栏中,或使用ecx schema export导出文件查看。
导入Schema文件
字符串创建
我们可以使用字符串编写Schema文件信息,然后使用ECSchema阅读器对字符串执行反序列化获得Schema文件。 ```csharp public static void ImportSchemaToDgnFile1(string unparsed) { DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件 ImportSchemaOptions options = new ImportSchemaOptions();//声明导入Schema选项
IECSchema TestSchema =DefineECSchema1();//定义Schema SchemaImportStatus impStatus = DgnECManager.Manager.ImportSchema(TestSchema, dgnFile, options);//导入ECSchema MessageBox.Show(“Schema Import Status:\n”+impStatus);//对话框输出导入是否成功 }
public static IECSchema DefineECSchema1() { string schemaXml = “<?xml version=\”1.0\” encoding=\”UTF-8\”?>”
+ "<ECSchema schemaName=\"ComplexSchema\" nameSpacePrefix=\"ComplexSchema\" version=\"1.0\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.2.0\">"
+ " <ECClass typeName=\"Contact\" isStruct=\"True\" isDomainClass=\"False\">"
+ " <ECProperty propertyName=\"Name\" typeName=\"string\" /> "
+ " <ECProperty propertyName=\"Age\" typeName=\"int\" /> "
+ " <ECArrayProperty propertyName=\"PhoneNumber\" typeName=\"string\" /> "
+ " </ECClass>"
+ " <ECClass typeName=\"StructClass\" isStruct=\"True\" isDomainClass=\"False\">"
+ " <ECProperty propertyName=\"StringProperty\" typeName=\"string\" /> "
+ " <ECProperty propertyName=\"IntProperty\" typeName=\"int\" /> "
+ " <ECArrayProperty propertyName=\"ArrayProperty\" typeName=\"string\" minOccurs=\"1\" maxOccurs=\"1\" /> "
+ " <ECArrayProperty propertyName=\"ContactData\" typeName=\"Contact\" isStruct=\"True\" /> "
+ " </ECClass>"
+ " <ECClass typeName=\"ComplexClass\" isDomainClass=\"True\">"
+ " <ECProperty propertyName=\"IntProperty\" typeName=\"int\" />"
+ " <ECProperty propertyName=\"StringProperty\" typeName=\"string\" /> "
+ " <ECProperty propertyName=\"DoubleProperty\" typeName=\"double\" /> "
+ " <ECProperty propertyName=\"DateTimeProperty\" typeName=\"dateTime\" />"
+ " <ECProperty propertyName=\"BooleanProperty\" typeName=\"boolean\" />"
+ " <ECProperty propertyName=\"APoint2d\" typeName=\"point2d\" />"
+ " <ECProperty propertyName=\"APoint3d\" typeName=\"point3d\" />"
+ " <ECProperty propertyName=\"ALong\" typeName=\"long\" />"
+ " <ECProperty propertyName=\"ABinary\" typeName=\"binary\" />"
+ " <ECArrayProperty propertyName=\"SimpleArrayProperty\" typeName=\"string\"/>"
+ " <ECArrayProperty propertyName=\"FixedArrayProperty\" typeName=\"string\" minOccurs=\"1\" maxOccurs=\"1\" />"
+ " <ECArrayProperty propertyName=\"StructArrayProperty\" typeName=\"StructClass\" isStruct=\"True\" />"
+ " <ECArrayProperty propertyName=\"FixedStructArrayProperty\" typeName=\"StructClass\" minOccurs=\"1\" maxOccurs=\"1\" isStruct=\"True\" />"
+ " <ECStructProperty propertyName=\"StructProperty\" typeName=\"StructClass\" />"
+ " </ECClass>"
+ "</ECSchema>";//设置EC Schema
ECSchemaXmlStringReader xmlReader = new ECSchemaXmlStringReader(schemaXml);//声明ECSchema阅读器
IECSchema deserializedSchema = xmlReader.Deserialize();//将EC Schema阅读器读取到的信息反序列化
return deserializedSchema;//返回ECSchema
}
在本案例中,名为ComplexSchema,版本为1.0的Schema文件被成功加载。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646293262197-6d20121f-d5be-4e51-a2d3-f3e0e37c54ad.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=370&id=ueb17fcb5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=370&originWidth=846&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31382&status=done&style=none&taskId=u937f4f3e-c702-4770-ba45-de427ab69ec&title=&width=846)<br />**图12 Schema导入结果**
<a name="vXF15"></a>
###### 代码创建
使用该方法可以使用代码的方法一次创建Schema与其中的EC类及属性。
```csharp
public static void ImportSchemaToDgnFile2(string unparsed)
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ImportSchemaOptions options = new ImportSchemaOptions();//声明导入Schema选项
IECSchema testSchema = DefineECSchema2();//定义Schema
SchemaImportStatus impStatus = DgnECManager.Manager.ImportSchema(testSchema, dgnFile, options);//导入ECSchema
MessageBox.Show("Schema Import Status:\n" + impStatus);//对话框输出导入是否成功
}
public static IECSchema DefineECSchema2()
{
IECSchema schema = new ECSchema("ComplexSchema2", 1, 1, "");//声明ECSchema
//create the Project class
ECClass prjClass = new ECClass("ProjectClass");//创建EC类
prjClass.Add(new ECProperty("ProjectID", Bentley.ECObjects.ECObjects.IntegerType));//在EC类中添加EC属性
prjClass.Add(new ECProperty("ProjectName", Bentley.ECObjects.ECObjects.StringType));//在EC类中添加EC属性
prjClass.Add(new ECProperty("ProjectCost", Bentley.ECObjects.ECObjects.DoubleType));//在EC类中添加EC属性
prjClass.IsCustomAttribute = false;//设置EC类是否为自定义属性
prjClass.IsDomainClass = true;//设置EC类是否是域类
schema.AddClass(prjClass);//在ECSchema中添加EC类
//create the Member class
ECClass memberClass = new ECClass("MemberClass");//声明EC类
memberClass.Add(new ECProperty("MemberName", Bentley.ECObjects.ECObjects.StringType));//在EC类中添加EC属性
memberClass.Add(new ECProperty("MemberID", Bentley.ECObjects.ECObjects.IntegerType));//在EC类中添加EC属性
memberClass.Add(new ECProperty("MemberRole", Bentley.ECObjects.ECObjects.StringType));//在EC类中添加EC属性
memberClass.IsCustomAttribute = false;//设置EC类是否为自定义属性
memberClass.IsDomainClass = true;//设置EC类是否是域类
schema.AddClass(memberClass);//在ECSchema中添加EC类
return schema;//返回ECSchema
}
在本案例中,名为ComplexSchema2,版本为1.1的Schema文件被成功加载。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646293358730-2c5e6957-82fa-4f2d-ae41-b307c6f734c6.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=369&id=u97924306&margin=%5Bobject%20Object%5D&name=image.png&originHeight=369&originWidth=847&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31544&status=done&style=none&taskId=u3a8ec7c8-cf78-42c2-aeb6-359bd66f272&title=&width=847)<br />**图13 Schema导入结果**
文件导入
使用该方法可以从外部Schema文件中获得工程属性信息并导入文件中。使用这种方法时需要确定导入Schema文件的路径与名称,然后导入文件即可。
public static void ImportSchemaToDgnFile3(string unparsed)
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ImportSchemaOptions options = new ImportSchemaOptions();//声明导入Schema选项
string searchpath = @"E://工作相关//20211213MS案例直播//直播资料//Part6//ECAndItemTypeIntroduction//Schema//";//设置ECSchema存放路径
IECSchemaLocater SearchPathLocater = new SearchPathSchemaFileLocater(searchpath);//根据存放路径获取ECSchema
Bentley.ECObjects.ECObjects.AddSchemaLocater(SearchPathLocater);//在EC对象中添加ECSchema定位器
string schemafullname = "ComplexSchema";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
if(null==testSchema)//判断是否成功获得ECSchema
{
MessageBox.Show("Schema not found, please check");//对话框输出未获得指定ECSchema
return;//返回
}
SchemaImportStatus impStatus = DgnECManager.Manager.ImportSchema(testSchema, dgnFile, options);//导入ECSchema
MessageBox.Show("Schema Import Status:\n" + impStatus);//在对话框中输出ECSchema导入状态
}
在本案例中,名为ComplexSchema的Schema文件被成功加载。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646294165763-9fd7f4fb-6380-403b-9a26-44e6e49d7275.png#clientId=u46cd4111-9de1-4&crop=0&crop=0.0155&crop=1&crop=1&from=paste&height=367&id=ued9a9239&margin=%5Bobject%20Object%5D&name=image.png&originHeight=367&originWidth=850&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31655&status=done&style=none&taskId=u3a3a841b-0500-405b-9ac1-9ef2ff1c12e&title=&width=850)<br />**图14 Schema导入结果**
创建EC实例
元素上创建EC实例
当我们导入Schema文件后,若要对元素赋予EC实例,那么首先需要找到需要赋予的ECSchema,再根据类名找到赋予元素的EC类,可在赋予前对EC类中的EC属性值进行修改,修改完成后在元素上创建EC实例。
public static void CreateECInstanceOnElem(string unparsed)
{
try
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
string schemafullname = "ComplexSchema";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
if (null == testSchema)//判断是否成功获得ECSchema
{
MessageBox.Show("Schema not found, please check");//对话框输出未获得指定ECSchema
return;//返回
}
IECClass ecClass = testSchema.GetClass("ComplexClass");//获得指定名称的EC类
DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnFile, ecClass);//获得EC实例启动器
StandaloneECDInstance instance = instanceEnabler.SharedWipInstance;
instance.SetInteger("IntProperty", 100);
IECArrayValue arrayValue = null;
if (null != (arrayValue = instance["FixedStructArrayProperty"] as IECArrayValue))
{
IECStructValue structValue;
structValue = arrayValue[0] as IECStructValue;
structValue["StringProperty"].StringValue = "MyStrVal1";
structValue["IntProperty"].IntValue = 11;
structValue = arrayValue[1] as IECStructValue;
structValue["StringProperty"].StringValue = "MyStrVal2";
structValue["IntProperty"].IntValue = 22;
}
#region Create ConeElement
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
DPoint3d topCenter = new DPoint3d(0, 0, 100000);//定义顶部圆锥(台)圆心坐标
DPoint3d bottomCenter = DPoint3d.Zero;//定义底部圆锥(台)圆心坐标
ConeElement cone = new ConeElement(dgnModel, null, 50000, 100000, topCenter, bottomCenter, DMatrix3d.Identity, true);//定义圆锥(台)元素
cone.AddToModel();//将圆锥(台)写入模型
#endregion
IDgnECInstance instanceOnElement = instanceEnabler.CreateInstanceOnElement(cone, instance, false);//在元素上创建EC实例
StatusInt status = instanceOnElement.ScheduleChanges(cone);//更新元素上的EC实例
if (status == StatusInt.Success)//判断是否更新成功
{
MessageBox.Show("Create EC On Element Success");//对话框输出创建成功的信息
}
}
catch (Exception ex)
{
MessageCenter.Instance.StatusMessage = ex.Message;//输出错误状态信息
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误警告信息
}
}
在本案例中可以发现名为"ComplexClass"的EC类生成实例被成功附加在元素上。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646294947552-5e06c07f-50b7-416f-88c2-51f32c00432b.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=777&id=u5c074fcb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=777&originWidth=1327&originalType=binary&ratio=1&rotation=0&showTitle=false&size=255236&status=done&style=none&taskId=ufa91a1e7-f44b-45cf-9217-f1c5070e37e&title=&width=1327)<br />**图15 元素上创建EC实例结果**
模型上创建EC实例
当我们导入Schema文件后,若要对模型赋予EC实例,那么首先需要找到需要赋予的ECSchema,再根据类名找到赋予元素的EC类,可在赋予前对EC类中的EC属性值进行修改,修改完成后在模型上创建EC实例。
public static void CreateECInstanceOnModel(string unparsed)
{
try
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
string schemafullname = "ComplexSchema";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
if (null == testSchema)//判断是否成功获得ECSchema
{
MessageBox.Show("Schema not found, please check");//对话框输出未获得指定ECSchema
return;//返回
}
IECClass ecClass = testSchema.GetClass("ComplexClass");//获得指定名称的EC类
DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnFile, ecClass);//获得EC实例启动器
IDgnECInstance instanceOnModel = instanceEnabler.CreateInstanceOnModel(dgnModel, instanceEnabler.SharedWipInstance);//在模型上创建EC实例
StatusInt status= instanceOnModel.WriteChanges();//更新模型上的EC实例
if (status==StatusInt.Success)//判断EC实例是否更新成功
{
MessageBox.Show("Create EC On Model Success");//对话框输出结果
}
}
catch (Exception ex)
{
MessageCenter.Instance.StatusMessage = ex.Message;//输出错误状态信息
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误警告信息
}
}
在本案例中可以发现名为"ComplexClass"的EC类生成实例被成功附加在模型上。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646295131420-57e34a81-24c2-4a2a-b6c9-9c7afd821639.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=772&id=u29b3d5c0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=772&originWidth=1329&originalType=binary&ratio=1&rotation=0&showTitle=false&size=204797&status=done&style=none&taskId=ud4ddee57-d050-4126-bb78-284f9403da5&title=&width=1329)<br />**图16 模型上创建EC实例结果**
文件上创建EC实例
当我们导入Schema文件后,若要对文件赋予EC实例,那么首先需要找到需要赋予的ECSchema,再根据类名找到赋予元素的EC类,可在赋予前对EC类中的EC属性值进行修改,修改完成后在文件上创建EC实例。
public static void CreateECInstanceOnFile(string unparsed)
{
try
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
string schemafullname = "ComplexSchema";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
if (null == testSchema)//判断是否成功获得ECSchema
{
MessageBox.Show("Schema not found, please check");//对话框输出未获得指定ECSchema
return;//返回
}
IECClass ecClass = testSchema.GetClass("ComplexClass");//获得指定名称的EC类
DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnFile, ecClass);//获得EC实例启动器
IDgnECInstance instanceOnFile = instanceEnabler.CreateInstanceOnFile(dgnFile, instanceEnabler.SharedWipInstance);//在文件上创建EC实例
StatusInt status = instanceOnFile.WriteChanges();//更新文件上的EC实例
if (status == StatusInt.Success)//判断EC实例是否更新成功
{
MessageBox.Show("Create EC On File Success");//对话框输出结果
}
}
catch (Exception ex)
{
MessageCenter.Instance.StatusMessage = ex.Message;//输出错误状态信息
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误警告信息
}
}
在本案例中可以发现名为"ComplexClass"的EC类生成实例被成功附加在文件上。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646295354968-095bd89a-8641-43bf-98a4-48912374e008.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=778&id=u723585df&margin=%5Bobject%20Object%5D&name=image.png&originHeight=778&originWidth=1483&originalType=binary&ratio=1&rotation=0&showTitle=false&size=289988&status=done&style=none&taskId=u2fe809ab-9cdd-4b57-adf4-e8b53da3edd&title=&width=1483)<br />**图17 文件上创建EC实例结果**
更新ECSchema
当我们需要修改ECSchema时,我们可以使用DgnECManager.Manager.UpdateSchema( )的方法对Schema中的内容进行修改。
public static void UpdateSchema(string unparsed)
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnECConnectionOptions options = new DgnECConnectionOptions();//声明EC连接选项
string schemafullname = "ComplexSchema";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
if (null == testSchema)//判断是否成功获得ECSchema
{
MessageBox.Show("Schema not found, please check");//对话框输出未获得指定ECSchema
return;//返回
}
IECClass ecClass = testSchema.GetClass("ComplexClass");//获得指定名称的EC类
ecClass.Add(new ECProperty("MemberName", Bentley.ECObjects.ECObjects.StringType));//在EC类中添加EC属性
ecClass.Add(new ECProperty("MemberID", Bentley.ECObjects.ECObjects.IntegerType));//在EC类中添加EC属性
ecClass.Add(new ECProperty("MemberRole", Bentley.ECObjects.ECObjects.StringType));//在EC类中添加EC属性
ecClass.Remove("IntProperty");//在EC类中移除指定EC属性
ecClass.Remove("StringProperty");//在EC类中移除指定EC属性
UpdateSchemaOptions uoption = new UpdateSchemaOptions();//声明ECSchema更新选项
SchemaUpdateStatus ustatus = DgnECManager.Manager.UpdateSchema(testSchema, dgnFile, uoption);//更新ECSchema
if (ustatus == SchemaUpdateStatus.Success)//判断是否更新成功
{
MessageBox.Show("Data update success");//对话框输出数据更新成功
}
else
{
MessageBox.Show("Data update failure:\n" + ustatus.ToString());//对话框输出更新失败原因
}
}
在本案例中我们对比可以发现,在名为"ComplexClass"EC类中,移除了IntProperty与StringProperty属性,添加了MemberName,MemberID与MemberRole属性。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646295690978-373d1236-75fb-4141-8d93-a35eaa61c1df.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=773&id=u068b474c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=773&originWidth=1327&originalType=binary&ratio=1&rotation=0&showTitle=false&size=224476&status=done&style=none&taskId=ude958d96-fa00-4411-87aa-38d3f3b1ff1&title=&width=1327)<br />**图18 Schema文件更新前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646295743895-df95baed-8cfd-4b71-80ca-85c47530b984.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=776&id=udf4d6b1a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=776&originWidth=1328&originalType=binary&ratio=1&rotation=0&showTitle=false&size=229837&status=done&style=none&taskId=ufbdee42e-099d-451a-a0cd-52341be8491&title=&width=1328)<br />**图19 Schema文件更新后**
修改EC实例属性值
当我们需要修改元素上挂接的EC实例中的属性值时,首先得到获得需要修改属性值的元素,然后找到执行EC类上的指定属性,对其值进行修改。
public static void ChangeECInstancePropertyValueOnElem(string unparsed)
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得模型空间中的图形元素
foreach (Element elem in elems)//遍历图形元素
{
DgnECInstanceCollection instCol = DgnECManager.Manager.GetElementProperties(elem, ECQueryProcessFlags.SearchAllClasses);//获得元素EC实例集
foreach (IDgnECInstance instance in instCol)//遍历属性集中的EC实例
{
if (instance.ClassDefinition.Name == "ComplexClass")//根据实例类名称条件筛选
{
instance.SetString("StringProperty", "Test for Change EC Instance Property on Element");//设置属性值
instance.WriteChanges();//更新文件上的EC实例
}
}
}
}
本案例中,名为"StringProperty"的EC属性将原来为空的属性值修改为"Test for Change EC Instance Property on Element"的字符串。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646296124475-b0411049-c4e8-4c30-9820-b96fa18d4b1d.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=778&id=u075a854a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=778&originWidth=1328&originalType=binary&ratio=1&rotation=0&showTitle=false&size=223085&status=done&style=none&taskId=u7f59bf79-fdf3-4bff-8bc1-a13ea3cfa52&title=&width=1328)<br />**图20 EC属性值修改前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646296189929-70e9475a-be55-44e3-9197-3d83cc5e3c08.png#clientId=u46cd4111-9de1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=779&id=u1aefc54e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=779&originWidth=1325&originalType=binary&ratio=1&rotation=0&showTitle=false&size=228710&status=done&style=none&taskId=u25f4fc9a-0dbe-46fd-9ec1-d6c18bb77d0&title=&width=1325)<br />**图21 EC属性值修改后**
移除元素上的EC实例
当我们移除元素上挂接的EC实例时,首先需要找到需要移除EC实例的元素,然后获取对应的EC实例后使用Delete( )执行EC实例删除的操作。
public static void RemoveECInstanceOnElem(string unparsed)
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
ModelElementsCollection elems= dgnModel.GetGraphicElements();//获得模型空间中的图形元素
foreach (Element elem in elems)//遍历图形元素
{
DgnECInstanceCollection instCol = DgnECManager.Manager.GetElementProperties(elem, ECQueryProcessFlags.SearchAllClasses);//获得元素EC实例集
foreach (IDgnECInstance instance in instCol)//遍历属性集中的EC实例
{
if (instance.ClassDefinition.Name == "ComplexClass")//根据实例类名称条件筛选
{
DeleteDgnECInstanceStatus state =instance.Delete();//删除EC实例
MessageBox.Show("Remove EC Instance On Elem Status:\n" + state.ToString());//对话框输出删除结果
}
}
}
}
创建ECRelationship
当我们需要建立EC类之间的关系时,就需要使用ECRelationship。首先我们需要在Schema文件中对用于关联的EC类与对应的ECRelationship进行定义,定义完成后才能实现对ECRelationship的挂接操作。为了说明问题,我们举一个较为简单的例子,下方的Schema文件中定义了三个EC类,分别名为”Widget”,”Gadget1”与”Gadget2”。而下方的ECRelationshipClass中将三者之间的关系进行定义,即名为”Widget”拥有”Gadget1”与”Gadget2”。
<?xml version="1.0" encoding="utf-8"?>
<ECSchema schemaName="Simple" nameSpacePrefix="demo" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
<ECClass typeName="Widget" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECClass typeName="Gadget1" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECClass typeName="Gadget2" isDomainClass="True">
<ECProperty propertyName="Manufacturer" typeName="string" />
</ECClass>
<ECRelationshipClass typeName="WidgetHasGadgets" description="WidgetHasGadgets" isDomainClass="True" strength="referencing" strengthDirection="forward">
<Source cardinality="(1,1)" roleLabel="has Gadgets" polymorphic="False">
<Class class="Widget" />
</Source>
<Target cardinality="(1,N)" roleLabel="are held by Widget" polymorphic="False">
<Class class="Gadget1" />
<Class class="Gadget2" />
</Target>
</ECRelationshipClass>
</ECSchema>
#region Create ECInstanceRelationship
private static IDgnECInstance gadgetInstance1;//声明ECInstance
private static IDgnECInstance gadgetInstance2;//声明ECInstance
private static IDgnECInstance widgetInstance;//声明ECInstance
public static void ECInstanceRelationshipOnElem(string unparsed)
{
IECSchema ecSimpleSchema = LoadSchema();//读取ECSchema
CreateWidget(ecSimpleSchema);//创建EC实例
CreateGadget(ecSimpleSchema);//创建EC实例
CreatingWidgetGadgetRelationship(ecSimpleSchema);//创建ECInstanceRelationship
}
private static IECSchema LoadSchema()
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ImportSchemaOptions options = new ImportSchemaOptions();//声明ECSchema导入选项
string searchpath = @"E://工作相关//20211213MS案例直播//直播资料//Part6//ECAndItemTypeIntroduction//Schema//";//设置ECSchema文件路径
IECSchemaLocater SearchPathLocater = new SearchPathSchemaFileLocater(searchpath);//根据存放路径获取ECSchema
Bentley.ECObjects.ECObjects.AddSchemaLocater(SearchPathLocater);//在EC对象中添加ECSchema定位器
string schemafullname = "Simple.01.00";//设置ECSchema全名
IECSchema testSchema =
Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);//根据名称定位ECSchema
DgnECManager.Manager.ImportSchema(testSchema, dgnFile, options);//导入ECSchema
return testSchema;//返回ECSchema
}
#region CreateInstances function
/// <summary>
/// creating line element and attaching widget instance.
/// </summary>
public static void CreateWidget(IECSchema ecSimpleSchema)
{
try
{
DgnFile activeDgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnECManager dgnECManager = DgnECManager.Manager;//获取DgnECManager
if (null == dgnECManager)//判断DgnECManager是否存在
return;//返回
if (null == ecSimpleSchema)//判断ECSchema是否存在
{
MessageCenter.Instance.StatusWarning = "ERROR_SCHEMANOTFOUND";//输出未找到ECSchema的提示
return;//返回
}
LineElement widgetLine = CreateLine(0, 0, -100, 100);//创建线元素
IECClass ecClass = ecSimpleSchema.GetClass("Widget");//在ECSchema中获取指定名称的EC类
DgnECInstanceEnabler widgetEnabler = dgnECManager.ObtainInstanceEnabler(activeDgnFile, ecClass);//获得EC实例启动器
ECDInstance widgetWipInstance = widgetEnabler.SharedWipInstance;//获得EC实例
widgetWipInstance.SetAsString("Manufacturer", "ACME Engineering");//设置对应属性值
widgetInstance = widgetEnabler.CreateInstanceOnElement(widgetLine, widgetWipInstance, false);//在元素上创建EC实例
MessageCenter.Instance.StatusMessage = "Success_WidgetCreate";//输出EC实例创建成功的信息
}
catch (Exception ex)
{
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误信息
}
}
/// <summary>
/// creating line element and attaching gadget instance.
/// </summary>
public static void CreateGadget(IECSchema ecSimpleSchema)
{
try
{
DgnFile activeDgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnECManager dgnECManager = DgnECManager.Manager;//获取DgnECManager
if (null == dgnECManager)//判断DgnECManager是否存在
return;//返回
if (null == ecSimpleSchema)//判断ECSchema是否存在
{
MessageCenter.Instance.StatusWarning = "ERROR_SCHEMANOTFOUND";//输出未找到ECSchema的提示
return;//返回
}
LineElement gadgetLine = CreateLine(0, 0, 0, 100);//创建线元素
IECClass ecGadgetClass1 = ecSimpleSchema.GetClass("Gadget1");//在ECSchema中获取指定名称的EC类
DgnECInstanceEnabler gadgetEnabler1 = dgnECManager.ObtainInstanceEnabler(activeDgnFile, ecGadgetClass1);//获得EC实例启动器
ECDInstance gadgetWipInstance1 = gadgetEnabler1.SharedWipInstance;//获得EC实例
gadgetWipInstance1.SetAsString("Manufacturer", "Sample App Gadget Manufacturer1");//设置对应属性值
gadgetInstance1 = gadgetEnabler1.CreateInstanceOnElement(gadgetLine, gadgetWipInstance1, false);//在元素上创建EC实例
IECClass ecGadgetClass2 = ecSimpleSchema.GetClass("Gadget2");
DgnECInstanceEnabler gadgetEnabler2 = dgnECManager.ObtainInstanceEnabler(activeDgnFile, ecGadgetClass2);//获得EC实例启动器
ECDInstance gadgetWipInstance2 = gadgetEnabler2.SharedWipInstance;//获得EC实例
gadgetWipInstance2.SetAsString("Manufacturer", "Sample App Gadget Manufacturer2");//设置对应属性值
gadgetInstance2 = gadgetEnabler2.CreateInstanceOnElement(gadgetLine, gadgetWipInstance2, false);//在元素上创建EC实例
MessageCenter.Instance.StatusMessage = "Success_GadgetCreate";//输出EC实例创建成功的信息
}
catch (Exception ex)
{
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误信息
}
}
/// <summary>
/// creating relationship between gadget and widget instance.
/// </summary>
public static void CreatingWidgetGadgetRelationship(IECSchema ecSimpleSchema)
{
try
{
DgnFile activeDgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnECManager dgnECManager = DgnECManager.Manager;//获取DgnECManager
if (null == dgnECManager)//判断DgnECManager是否存在
return;//返回
if (null == ecSimpleSchema)//判断ECSchema是否存在
{
MessageCenter.Instance.StatusWarning = "ERROR_SCHEMANOTFOUND";//输出未找到ECSchema的提示
return;//返回
}
string widgetHasGadgetClassName = "WidgetHasGadgets"; //设置ECRelationship名称,其中ECRelationship名称已经存在ECShema中
IECRelationshipClass widgetHasGadgetRelationshipClass = ecSimpleSchema.GetClass(widgetHasGadgetClassName) as IECRelationshipClass;//获得ECRelationship
DgnECRelationshipEnabler relationshipEnabler = dgnECManager.ObtainDgnECRelationshipEnabler(activeDgnFile, widgetHasGadgetRelationshipClass);//为IECRelationshipClass-DgnFile对创建ECRelationship启动器
if (null == relationshipEnabler)//判断ECRelationship启动器是否成功激活
{
MessageCenter.Instance.StatusWarning = "ERROR_REL_ENABLER";//输出ECRelationship启动器不可用的提示
return;//返回
}
IECRelationshipInstance relationshipInstance = relationshipEnabler.CreateRelationshipOnElement(widgetInstance, gadgetInstance1);//在元素上创建ECRelationship实例
if (null == relationshipInstance)//判断ECRelationship实例是否存在
{
MessageCenter.Instance.StatusWarning = "ERROR_REL_INSTANCE";//输出ECRelationship实例获取失败的提示
return;//返回
}
relationshipInstance = relationshipEnabler.CreateRelationshipOnElement(widgetInstance, gadgetInstance2);//在元素上创建ECRelationship实例
if (null == relationshipInstance)//判断ECRelationship实例是否存在
{
MessageCenter.Instance.StatusWarning = "ERROR_REL_INSTANCE";//输出ECRelationship实例获取失败的提示
return;//返回
}
}
catch (Exception ex)
{
MessageCenter.Instance.StatusWarning = ex.Message;//输出错误信息
}
}
private static LineElement CreateLine(int x1, int y1, int x2, int y2)
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
DSegment3d segment = new DSegment3d(x1, y1, x2, y2);//创建直线几何
LineElement line = new LineElement(dgnModel, null, segment);//创建线元素
line.AddToModel();//将线元素写入模型
return line;//返回线元素
}
#endregion
#endregion
从本案例中的结果可以看出,除了在线上分别赋予了名为"Widget","Gadget1"与"Gadget2"EC类对应的EC实例,同时,EC类之间的上下级关系也在浏览器窗体中得以体现。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646358810788-f11c74cf-3786-432b-bb4f-72ef40b7b68f.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=543&id=u36badaab&margin=%5Bobject%20Object%5D&name=image.png&originHeight=543&originWidth=1185&originalType=binary&ratio=1&rotation=0&showTitle=false&size=67396&status=done&style=none&taskId=ub2569636-7706-484c-b89c-02142d97576&title=&width=1185)<br />**图24 ECECRelationship挂接结果**
ItemType操作实际案例
ItemType作为EC的简化版,其操作更加便捷,同时拥有可视化的操作界面,对于使用软件的人来说对于ItemType的创建,删除,修改,更新操作更加便捷。因此对于第一次接触工程属性或工程属性构成较为简单的使用场景下,我们推荐使用ItemType进行工程属性的赋予。
创建ItemType
创建ItemType的方式与我们在图形界面中的创建方式基本一致,遵循的方法为:创建ItemTypeLibrary,创建ItemType,为ItemType添加属性,如有需要可添加默认属性值,设置完成后将ItemTypeLibrary中的信息进行更新。![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646359806821-94f930d3-defc-47d9-9b1e-7464d1a4ed99.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=511&id=u0758fc86&margin=%5Bobject%20Object%5D&name=image.png&originHeight=511&originWidth=998&originalType=binary&ratio=1&rotation=0&showTitle=false&size=41429&status=done&style=none&taskId=u0f6811c6-3313-4432-9811-b6a5d260e4c&title=&width=998)<br />**图25 ItemType工具**
public static void CreateItemType(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//根据声明名称获取对应的ItemTypeLibrary
if (null == itemTypeLibrary)//判断文件中是否存在同名ItemTypeLibrary
{
itemTypeLibrary = ItemTypeLibrary.Create(itemLibName, dgnFile);//若不存在则进行创建
}
itemTypeLibrary.AddItemType(itemTypeName);//在ItemTypeLibrary中创建名为testItemTypeName的ItemType
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//获取创建的ItemType
CustomProperty intProperty = itemType.AddProperty("IntProperty");//对该ItemType添加名为IntProperty的属性
intProperty.Type = CustomProperty.TypeKind.Integer;//设置IntProperty的属性类型
CustomProperty strProperty = itemType.AddProperty("StrProperty");//对该ItemType添加名为StrProperty的属性
strProperty.Type = CustomProperty.TypeKind.String;//设置StrProperty的属性类型
strProperty.DefaultValue = "test string";//为StrProperty设置默认值,若不进行设置则默认为空
bool result= itemTypeLibrary.Write();//将ItemTypeLibrary中的信息进行写入更新
if (result)//判断写入是否成功
{
MessageBox.Show("Input ItemType Success");//若成功输出输入ItemType成功的提示框
}
}
在本案例中,首先在文件中查看是否存在同名的("testLib")的ItemTypeLibrary,若不存在则执行创建操作。然后在指定库中添加名为"testItemTypeName"的ItemType,并对其中的属性及默认属性值进行设置,完成后更新信息。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646360423194-79acea00-985b-4790-861b-d5ac5d839fd2.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=508&id=u9172a50d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=508&originWidth=1000&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46734&status=done&style=none&taskId=uab104bc5-858c-409d-886d-170ed22cc4b&title=&width=1000)<br />**图26 ItemType创建结果**
删除ItemType
当我们需要删除ItemTypeLibrary中指定的ItemType时,需要使用RemoveItemType( )方法达到相应的效果。步骤为首先在文件中获得指定名称的ItemTypeLibrary中的ItemType,然后执行删除操作。
public static void DeleteItemType(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//根据声明名称获取对应的ItemTypeLibrary
if (null == itemTypeLibrary)//判断文件中是否存在同名ItemTypeLibrary
{
MessageBox.Show("Can't find itemType library!");//若文件中不存在同名ItemTypeLibrary,则对话框提示未找到ItemTypeLibrary的提示框
return;//返回
}
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//通过名称在ItemTypeLibrary中查找对应的ItemType
bool result = itemTypeLibrary.RemoveItemType(itemType);//删除ItemTypeLibrary中的指定ItemType
if (result)//判断在ItemTypeLibrary是否将指定ItemType成功删除
{
MessageBox.Show("Remove ItemType Success");//若删除成功则在对话框中输出移除ItemType成功的提示
}
itemTypeLibrary.Write();//将ItemTypeLibrary中的信息进行写入更新
}
在本案例中,首先获得名为"testLib"的ItemTypeLibrary中名为"testItemTypeName"的ItemType,随后对指定名称的ItemType执行删除操作。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646361569147-0c8c68a3-bc52-474f-885f-72f66c719570.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=514&id=u714a24d6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=514&originWidth=1003&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46994&status=done&style=none&taskId=ub92514fa-6303-4327-aebf-c37a2267230&title=&width=1003)<br />**图27 命令执行前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646363192480-4e64eb11-7d79-4efc-9302-a28f9673f045.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=512&id=uf5ba3aa5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=512&originWidth=1003&originalType=binary&ratio=1&rotation=0&showTitle=false&size=28166&status=done&style=none&taskId=uc1de7d83-278b-4c4f-bcfe-18e9858c4ae&title=&width=1003)<br />**图28 命令执行结果**
删除ItemTypeLibrary
当我们需要删除整个ItemTypeLibrary时,需要使用Delete()方法达到相应的效果。步骤为首先在文件中获得指定名称的ItemTypeLibrary,然后执行删除操作。在本案例中,名为”testLib”的ItemTypeLibrary被成功删除。
public static void DeleteItemTypeLib(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//根据声明名称获取对应的ItemTypeLibrary
if (null == itemTypeLibrary)//判断文件中是否存在同名ItemTypeLibrary
{
MessageBox.Show("Can't find itemType library!");//若文件中不存在同名ItemTypeLibrary,则对话框提示未找到ItemTypeLibrary的提示框
return;//返回
}
SchemaDeleteStatus status= itemTypeLibrary.Delete();//删除指定的ItemTypeLibrary
MessageBox.Show("ItemTypeLib remove status:\n"+status.ToString());//在对话框中输出ItemTypeLibrary的删除结果
}
挂接ItemType
当我们创建成功ItemType及其属性后,若想对象真正表现工程属性的特征,那么就需要将工程属性挂接到模型中。关于挂接ItemType的操作方法为首先获得需要进行挂接的对象与用于挂接的ItemType,声明元素的CustomItemHost后对其添加ItemType实例,并可对其中的属性值进行设置,设置完成后更新ItemType信息。<br />**扩展知识:**<br />**DomainClass:**<br /> 域类从用户或应用程序提供的ECClass(例如,由CustomItemType定义)获得。ECClass中可用于参数化建模的所有ECProperties(即可转换为ParameterType enum定义的类型之一)将成为“域”参数。域参数支持比本地(“工作”)参数更有限的修改,尤其是它们的名称和类型不能修改,因为它们是由用户的ECSchema定义的。域参数的范围和可见性可以修改,其值可以通过表达式定义。提供的实例的属性值将提供每个域参数的初始值。这些值也将应用于所有IParameterSets。
public static void AttachItemTypeToElem(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
#region Create ConeElement
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
DPoint3d topCenter = new DPoint3d(0, 0, 100000);//定义顶部圆锥(台)圆心坐标
DPoint3d bottomCenter = DPoint3d.Zero;//定义底部圆锥(台)圆心坐标
ConeElement cone = new ConeElement(dgnModel, null, 50000, 100000, topCenter, bottomCenter, DMatrix3d.Identity, true);//定义圆锥(台)元素
#endregion
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//根据声明名称获取对应的ItemTypeLibrary
if (null == itemTypeLibrary)//判断文件中是否存在同名ItemTypeLibrary
{
MessageBox.Show("Can't find ItemType Library");//若文件中不存在同名ItemTypeLibrary,则对话框提示未找到ItemTypeLibrary的提示框
return;//返回
}
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//根据声明名称获取对应的ItemType
CustomItemHost host = new CustomItemHost(cone, true);//声明元素的CustomItemHost
IDgnECInstance item = host.ApplyCustomItem(itemType, true);//对CustomItemHost添加ItemType得到EC实例
item.SetValue("IntProperty", 123);//设置属性值
item.SetValue("StrProperty", "CCCC");
//Set Domain class on Item type.
EditParameterDefinitions defs = EditParameterDefinitions.GetForModel(dgnModel);//获得模型中的参数定义
DgnECInstanceEnabler enabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnFile, itemType.ECClass);//获得文件中使用指定EC类的EC实例
if (null != enabler && enabler.SupportsCreateInstanceOnElement)//判断是否是否支持对元素挂接EC实例
defs.SetDomainParameters(enabler.SharedWipInstance);//对参数定义设置域参数
item.ScheduleChanges(cone);//对圆锥(台)元素更新ItemType信息
cone.AddToModel();//将圆锥(台)写入模型
}
读取元素挂接属性
当我们需要根据工程属性中的参数执行不同操作时,需要查看其属性值,而查看属性值的方法是首先找到需要查询的元素,获得其EC实例,然后从对应ItemType中获得属性名称,根据属性名称查看EC实例中该属性的属性值。
public static void ReadItemTypeOnElem(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素
foreach (Element elem in elems)//遍历模型中的所有图形元素
{
CustomItemHost host = new CustomItemHost(elem, true);//声明CustomItemHost
IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);//获得CustomItemHost中指定ItemTypeLibrary中的ItemType的EC实例
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//从文件中中获得指定名称的ItemTypeLibrary
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//根据声明名称获取对应的ItemType
CustomProperty property = itemType.GetPropertyByName("StrProperty");//根据声明名称获取对应的CustomProperty
string internalName = property.InternalName;//获得属性内部名称
IECPropertyValue val = item.GetPropertyValue(internalName);//根据属性名称获得属性值
MessageBox.Show(val != null ? val.StringValue : "val==null");//在对话框中输出属性值
}
}
在本案例中,对挂接名为"testLib"的ItemTypeLibrary中名为"testItemTypeName"的ItemType中"StrProperty"值进行查看,从结果可以获得其属性值为"CCCC"。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646377137540-d3a6fec1-5bbc-44d4-9916-986b5d7f5f56.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=542&id=ud9a10689&margin=%5Bobject%20Object%5D&name=image.png&originHeight=542&originWidth=1059&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72373&status=done&style=none&taskId=u3c8e03bb-7f23-4166-b546-82fed169d99&title=&width=1059)<br />**图34 元素挂接的工程属性**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646377113731-e505ea20-c8b8-495c-ad48-f650a581bffd.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=132&id=ud690b5a2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=132&originWidth=114&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1112&status=done&style=none&taskId=u5be34365-3555-4597-a3f1-7b542377f66&title=&width=114)<br />**图35 工程属性值查询结果**
取消挂接ItemType
当我们需要对挂接在元素上的工程属性取消挂接时,需要使用ScheduleDelete( )移除元素上的ItemType,实现的步骤大致为获取需要取消工程属性挂接的元素,获得其对应的EC实例,在EC实例中删除元素后对元素进行更新。
public static void DetachItemTypeOnElem(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素
foreach (Element elem in elems)//遍历模型中的所有图形元素
{
Element newElem = elem;//声明元素
CustomItemHost host = new CustomItemHost(newElem, true);//声明元素的CustomItemHost
IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);//获得CustomItemHost中指定ItemTypeLibrary中的ItemType的EC实例
item.ScheduleDelete(newElem);//移除元素的ItemType
newElem.ReplaceInModel(elem);//将元素取代
}
}
修改工程属性值
当我们需要修改工程属性值时,大致的步骤为首先获得元素上挂接的EC实例,然后再对应的ItemTypeLibrary中获得对应的ItemType与需要修改的属性,对其属性值进行设置,设置完成后修改元素上挂接的ItemType并对元素执行更新操作。
public static void ChangeItemTypeValueOnElem(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型空间
ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素
foreach (Element elem in elems)//遍历模型中的所有图形元素
{
Element newElem = elem;//声明元素
CustomItemHost host = new CustomItemHost(elem, true);//声明元素的CustomItemHost
IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);//获得CustomItemHost中指定ItemTypeLibrary中的ItemType的EC实例
if (item!=null)//判断是否存在指定要求的EC实例
{
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//从文件中中获得指定名称的ItemTypeLibrary
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//根据声明名称获取对应的ItemType
CustomProperty property = itemType.GetPropertyByName("StrProperty");//根据声明名称获取对应的CustomProperty
string internalName = property.InternalName;//获得属性内部名称
IECPropertyValue val = item.GetPropertyValue(internalName);//根据属性名称获得属性值
val.StringValue = "Changed string";//设置属性值
item.ScheduleChanges(elem);//修改元素的ItemType
newElem.ReplaceInModel(elem);//将元素取代
}
}
}
在本案例中,我们将属性名为"StrProperty"的属性值,由原来的"CCCC"修改为"Changed string"。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646378325819-4589669d-b53b-4de5-915f-f5043845d226.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=543&id=uc2e030b8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=543&originWidth=1060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72265&status=done&style=none&taskId=u1678154e-9660-4f4a-a299-01bcc9c9bc4&title=&width=1060)<br />**图38 命令执行前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646378352677-c2cee6f8-d758-4b52-a2a0-9a93a85c03b2.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=542&id=u419ba355&margin=%5Bobject%20Object%5D&name=image.png&originHeight=542&originWidth=1058&originalType=binary&ratio=1&rotation=0&showTitle=false&size=73101&status=done&style=none&taskId=u7b717872-cc76-4e1a-bb30-0dfb4b1127f&title=&width=1058)<br />**图39 命令执行结果**
添加ItemType属性
当我们的工程属性有变动需要执行添加ItemType属性操作时,我们就需要使用AddProperty( )来对已有的ItemType添加指定的属性,此时所有元素挂接了的该ItemType都会同步更新。
public static void AddItemTypeProperty(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//从文件中中获得指定名称的ItemTypeLibrary
if (null == itemTypeLibrary)//判断是否成功获取ItemTypeLibrary
{
MessageBox.Show("Find item type lib failure,please check");//对话框输出未找到指定ItemTypeLibrary
return;//返回
}
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//根据声明名称获取对应的ItemType
if (null == itemType)//判断是否成功获取ItemType
{
MessageBox.Show("Find item type failure,please check");//对话框输出未找到指定ItemType
return;//返回
}
CustomProperty douProperty = itemType.AddProperty("DoubleProperty");//在ItemType添加属性
douProperty.Type = CustomProperty.TypeKind.Double;//设置属性类型
douProperty.DefaultValue = 0.01;//设置属性默认值
bool result = itemTypeLibrary.Write();//将修改后的ItemTypeLibrary更新写入
if (result)//判断是否写入成功
{
MessageBox.Show("Add ItemType Property Success");//对话框输出添加ItemType属性成功
}
}
在本案例中,在名为"testItemTypeName"的ItemType中添加了一个名为"DoubleProperty"的double类属性,并设置其默认值为0.01,此时,元素上挂接了该ItemType也同步执行了添加属性的更新。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646379171684-f620b2b3-40b5-464c-bfa9-e61492d2ca56.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=uda463312&margin=%5Bobject%20Object%5D&name=image.png&originHeight=540&originWidth=1060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72402&status=done&style=none&taskId=ud19860cb-70ae-463a-8934-7c239ce768c&title=&width=1060)<br />**图40 命令执行前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646379206772-14d7f232-0423-4632-a4b3-317591ee71ac.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=541&id=ua202b046&margin=%5Bobject%20Object%5D&name=image.png&originHeight=541&originWidth=1060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=73368&status=done&style=none&taskId=uc9ab3fc4-f673-405c-bc73-85bfb9016d6&title=&width=1060)<br />**图41 命令执行结果**
移除ItemType属性
当我们的工程属性有变动需要执行移除ItemType属性操作时,我们就需要使用RemoveProperty( )来对已有的ItemType移除指定的属性,此时所有元素挂接的该ItemType都会同步更新。
public static void RemoveItemTypeProperty(string unparsed)
{
string itemLibName = "testLib";//设置ItemTypeLibrary的名称
string itemTypeName = "testItemTypeName";//设置ItemType的名称
string propertyName = "StrProperty";//设置属性名称
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);//从文件中中获得指定名称的ItemTypeLibrary
if (null == itemTypeLibrary)//判断是否成功获取ItemTypeLibrary
{
MessageBox.Show("Find item type lib failure,please check");//对话框输出未找到指定ItemTypeLibrary
return;//返回
}
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);//根据声明名称获取对应的ItemType
if (null == itemType)//判断是否成功获取ItemType
{
MessageBox.Show("Find item type failure,please check");//对话框输出未找到指定ItemType
return;//返回
}
CustomProperty property = itemType.GetPropertyByName(propertyName);//在ItemType中根据名称获得CustomProperty
if (null==property)//判断是否存在指定CustomProperty
{
MessageBox.Show("Find item type property failure,please check");//对话框输出
return;//返回
}
itemType.RemoveProperty(property);//移除ItemType上的指定属性
bool result = itemTypeLibrary.Write();//将修改后的ItemTypeLibrary更新写入
if (result)//判断写入是否成功
{
MessageBox.Show("Remove ItemType Property Success");//在对话框中输出移除ItemType属性成功
}
}
在本案例中,在名为"testItemTypeName"的ItemType中移除了一个名为"StrProperty"的属性,此时,元素上挂接的该ItemType也同步执行了移除属性的更新。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646379429506-8f7f1bf6-e233-4cae-b2aa-ec9a9e59aacc.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=541&id=u9df3671e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=541&originWidth=1060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=73271&status=done&style=none&taskId=ud9b9b7bd-79ca-44e0-9308-78f98a62833&title=&width=1060)<br />**图42 命令执行前**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21640708/1646379451974-41f0d6f9-dd7f-4e28-ae0b-b0701f8e5ac4.png#clientId=uda556bb7-786e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=542&id=u6b2fa30d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=542&originWidth=1056&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72272&status=done&style=none&taskId=u1f9b74dc-3c55-41b6-bcd7-33c9bdfa4a6&title=&width=1056)<br />**图43 命令执行结果**