Grouping and Sorting ECProperties in EC property pane

In MicroStation properties are displayed in certain categories(groups). Each Category contain different properties in it.

These category and property display sequence can be controlled using CustomAttributes.  So, this blog provides information and code snippets which demonstrates "How to do Grouping and sorting ECProperties in EC property pane".

1. Category sorting : 

         Category sorting is achieved through Category custom attribute, available in EditorCustomAttributes schema. Category custom attribute contains different element and they are as follows:

         Name : Name of the category 

         DisplayLabel : Display label of the category

         Priority : Represents integer value which determines the position of the category in the EC Property pane. Categories are positioned in higher to lower value sequence. 

         Category sorting field contains different value. If someone wants to display category at first position then they need add Priority value more than 400000.

         Expand : Boolean value represents category should be shown displayed expanded or collapsed (if not specified value is false)  

<ECClass typeName="Widget" isDomainClass="True">
    <ECCustomAttributes>
      <Category xmlns="EditorCustomAttributes.01.00">
        <Name>WidgetCategory</Name>
        <DisplayLabel>Sorted Properties - Widget</DisplayLabel>
        <Priority>400100</Priority>
        <Expand>True</Expand>
      </Category>
    </ECCustomAttributes>

2. Property sorting : 

Property sorting is achieved through PropertyPriority custom attribute, available in EditorCustomAttributes schema. Properties are being sorted within category. PropertyPriority custom attribute contains following element:

 Priority : Represents integer value which determines the position of the property in the specific category. There is no specific range for Priority.   

3. Using Category and Property sorting 

The following schema contains 3 classes : 

            a. Widget class which contains Category and PropertyPriority  attribute defined

            b. Gadget class which has no Category and PropertyPriority  attribute defined

           c. Slab class with no category custom attribute. 

<?xml version="1.0" encoding="utf-8"?>
<ECSchema schemaName="ApplyPriorityToCategoryAndProperty" nameSpacePrefix="demo" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
  <ECSchemaReference name="EditorCustomAttributes" version="01.00" prefix="beca" />

  <ECClass typeName="Widget" isDomainClass="True">
    <ECCustomAttributes>
      <Category xmlns="EditorCustomAttributes.01.00">
        <Name>WidgetCategory</Name>
        <DisplayLabel>Sorted Properties - Widget</DisplayLabel>
        <Priority>400100</Priority>
        <Expand>True</Expand>
      </Category>
    </ECCustomAttributes>
    <ECProperty propertyName="Name" typeName="string" >
      <ECCustomAttributes>
        <PropertyPriority xmlns="EditorCustomAttributes.01.00">
          <Priority>200</Priority>
        </PropertyPriority>
      </ECCustomAttributes>
    </ECProperty>
    <ECProperty propertyName="Manufacturer" typeName="string" >
      <ECCustomAttributes>
        <PropertyPriority xmlns="EditorCustomAttributes.01.00">
          <Priority>180</Priority>
        </PropertyPriority>
      </ECCustomAttributes>
    </ECProperty>
    <ECProperty propertyName="Address" typeName="string" >
      <ECCustomAttributes>
         <PropertyPriority xmlns="EditorCustomAttributes.01.00">
          <Priority>150</Priority>
        </PropertyPriority>
      </ECCustomAttributes>
    </ECProperty>
  </ECClass>
  <ECClass typeName="Gadget" isDomainClass="True">
    <ECProperty propertyName="Name" typeName="string" />
    <ECProperty propertyName="Manufacturer" typeName="string" />
    <ECProperty propertyName="Address" typeName="string" />
  </ECClass>
  <ECClass typeName="Slab" isDomainClass="True">
    <ECProperty propertyName="Name" typeName="string" />
  </ECClass>
</ECSchema>

After using this schema and adding properties on line element we get following result : 

            a. The Widget Category is listed at the top in EC Property Pane. It has picked the name from DisplayLabel element from Category CustomAttribute.

                The properties inside the Widget category are sorted as per the PropertyPriority CustomAttribute.

            b. The Gadget category has no  Category CustomAttribute and PropertyPriority CustomAttribute defined.

                The name of the Category is picked from the class it is representing. 

            c.  I have created Category in managed code for Slab class as follows:

                 Slab Category position can be controlled by setting Priority attribute e.g. ECPropertyPane.SetPriority().   

                 Predefined priority values are available e.g. ECPropertyPane.PropertySortPriorityVeryHigh 

IECInstance slabCategory = ECPropertyPane.CreateCategory("Slab", "Civil Slab", "Slab Category", ECPropertyPane.CategorySortPriorityHigh, true);
property.SetCustomAttribute(slabCategory);
ECPropertyPane.SetCategory(property, slabCategory);

4. Creating category in native code(C++) : 

We don't have direct native APIs for creating or getting category. We can use standard custom attribute setting/getting procedure.. Here is sample code : 

	ECPropertyP ecProperty = ecClass->GetPropertyP(L"NewProperty");
	SchemaInfo  schemaInfo (SchemaKey(L"EditorCustomAttributes", 1, 0), *dgnFile);
	ECSchemaPtr editorCustomAttributes = dgnECManager.LocateExternalSchema (schemaInfo, SCHEMAMATCHTYPE_LatestCompatible);
	ECClassP extendType = editorCustomAttributes->GetClassP(L"Category");
	IECInstancePtr ecInstanceCategory = extendType->GetDefaultStandaloneEnabler()->CreateInstance();
	ECValue v(L"SampleCategory");
	ecInstanceCategory->SetValue(L"Name", v);
	ECValue v(L"SampleCategory Label");
	ecInstanceCategory->SetValue(L"DisplayLabel", v);
	ECValue v(4000000);
	ecInstanceCategory->SetValue(L"Priority", v);
	ECValue v(True);
	ecInstanceCategory->SetValue(L"Expand", v);
	schema->AddReferencedSchema (*editorCustomAttributes);
    property->SetCustomAttribute (*ecInstanceCategory);