EC属性预选值


我们在使用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属性。