我们在使用EC机制给元素添加自定义属性时,有时会需要给某些自定义属性设置预定义的可选值,例如钢材的规格等。那么如何给EC属性设置这些可选值呢?我们可以通过“EditorCustomAttributes”中的名为"StandardValues"(如下所示)这个CustomAttributeClass来实现。
<ECClass typeName="StandardValues" description="Sets the display strings for standard integer values for an IECProperty" isDomainClass="False" isCustomAttributeClass="True">
<ECProperty propertyName="MustBeFromList" typeName="boolean" />
<ECArrayProperty propertyName="ValueMap" typeName="ValueMap" minOccurs="0" maxOccurs="unbounded" isStruct="True" />
</ECClass>
这个ECClass有两个属性"MustBeFromList"和"ValueMap"。"MustBeFromList"属性用来控制我们的EC属性值是否只能来自于预设值,"ValueMap"用来设置预设值。"ValueMap"这个属性的类型又是通过另外同名的ECClass来定义的,如下所示:
<ECClass typeName="ValueMap" isStruct="True" isDomainClass="True">
<ECProperty propertyName="DisplayString" typeName="string">
<ECCustomAttributes>
<Localizable xmlns="EditorCustomAttributes.01.02" />
</ECCustomAttributes>
</ECProperty>
<ECProperty propertyName="Value" typeName="int" />
</ECClass>
其包含两个属性"DisplayString"和"Value"。"DisplayString"用来设置我们的属性最终显示的字符串,"Value"用来设置字符串对应的真实数据值。如下是我们的测试代码下载链接:
communities.bentley.com/.../3441.ECCustomAttributes_5F00_StandardValues.7z
项目编译后,启动Mstn打开任意dgn文件,选中一个图形元素以后,打开元素属性对话框。执行keyin命令“mdl load ECCustomAttributes_StandardValues;eccustomattributes_standardvalues test”。在元素属性对话框中可以看到元素属性中会增加如下所示的EC属性:
在属性值输入框中单击鼠标左键,将输入焦点设置到此输入框时,会看到属性值输入框的最右边会出现一个下拉箭头,单击此下拉箭头可以弹出预设值的选项,如下图所示:
选中其中某个值,就可以将这个EC属性设置为对应的值。我们在的命令对应的命令函数为KeyinCommands.TestFun,在此函数中我们获取当前用户选中的第一个元素,将此元素作为参数调用ECProgramming的AddECInstanceToElement函数。AddECInstanceToElement函数如下所示:
public static void AddECInstanceToElement(Element ele)
{
IECSchema ecSchema = null;
DgnECManager manager = DgnECManager.Manager;
IEnumerable<string> schemaNames = manager.DiscoverSchemas(Session.Instance.GetActiveDgnFile(), ReferencedModelScopeOption.All, true);
foreach (string schemaName in schemaNames)
{
if (schemaName.Split('.')[0] == NameECSchema)
{
FindInstancesScope scopeTemp = FindInstancesScope.CreateScope(Session.Instance.GetActiveDgnFile(), new FindInstancesScopeOption());
int verMaj = 01, verMin = 0;
ecSchema = DgnECManager.Manager.LocateSchemaInScope(scopeTemp, NameECSchema, verMaj, verMin, SchemaMatchType.Latest);
break;
}
}
if (null == ecSchema)
{
ecSchema = CreateECSchema();
SchemaImportStatus schemaImportStatus = manager.ImportSchema(ecSchema, Session.Instance.GetActiveDgnFile(), new ImportSchemaOptions());
if (schemaImportStatus != SchemaImportStatus.Success)
{
return;
}
}
IECClass ecClass = ecSchema.GetClass(NameECClass);
if (ecClass == null)
{
return;
}
FindInstancesScope scope = FindInstancesScope.CreateScope(ele, new FindInstancesScopeOption(DgnECHostType.Element, true));
ECQuery query = new ECQuery(ecClass);
using (DgnECInstanceCollection ecInstances = manager.FindInstances(scope, query))
{
int cnt = ecInstances.Count();
if (cnt > 0)
{
foreach (IDgnECInstance dgnEcIns in ecInstances)
{
dgnEcIns.SetInteger(NameProp1, 3);
dgnEcIns.WriteChanges();
}
return;
}
DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnFile(), ecClass);
StandaloneECDInstance instance = instanceEnabler.SharedWipInstance;
instance.SetInteger(NameProp1, 2);
instanceEnabler.CreateInstanceOnElement(ele, instance, false);
}
}
在此函数中我们首先检查当前dgn文件中是否已经存在我们要创建的ECSchema的定义,如果存在我们就不需要创建,直接获取已存在的ECSchema即可。如果不存在我们再调用CreateECSchema函数去创建,CreateECSchema函数如下所示:
public static ECSchema CreateECSchema()
{
ECSchema ecSchema = new ECSchema(NameECSchema, 1, 0, NSPre);
IECClass ecClass = ecSchema.AddClass(NameECClass);
ecClass.IsDomainClass = true;
IECProperty ecprop1 = ecClass.AddProperty(NameProp1, ECObjects.IntegerType);
FindInstancesScope scopeTemp = FindInstancesScope.CreateScope(Session.Instance.GetActiveDgnFile(), new FindInstancesScopeOption());
int verMaj = 1, verMin = 3;
IECSchema schemaCustomAtt = DgnECManager.Manager.LocateDeliveredSchema("EditorCustomAttributes", verMaj, verMin,
SchemaMatchType.Latest, Session.Instance.GetActiveDgnFile());
if (schemaCustomAtt != null)
{
IECClass ecClassCate = schemaCustomAtt.GetClass("StandardValues");
IECInstance ecInsCate = ecClassCate.CreateInstance();
ecInsCate.SetBoolean("MustBeFromList", true);
IECPropertyValue iECPropVal = ecInsCate["ValueMap"];
IECArrayValue iECArrVal = iECPropVal as IECArrayValue;
IECStructValue ecStruVal = iECArrVal[0] as IECStructValue;
ecStruVal["Value"].IntValue = 1;
ecStruVal["DisplayString"].StringValue = "One";
ecStruVal = iECArrVal[1] as IECStructValue;
ecStruVal["Value"].IntValue = 2;
ecStruVal["DisplayString"].StringValue = "Two";
ecStruVal = iECArrVal[2] as IECStructValue;
ecStruVal["Value"].IntValue = 3;
ecStruVal["DisplayString"].StringValue = "Three";
ecprop1.SetCustomAttribute(ecInsCate);
}
return ecSchema;
}
在这个函数中我们首先创建好我们的ECSchema的定义,然后去获取“EditorCustomAttributes“中的名为"StandardValues"的ECClass,创建其ECInstance,设置好相应的值即可。创建好ECSchema的定义后,我们在AddECInstanceToElement函数中首先检查是元素是否已经存在相应的EC属性,如果已经存在我们只是更改了一下其属性值。如果不存在我们才给元素添加新的EC属性。