MicroStation .NET: Harvest Item Type Instance Data

  • Products
  • Services
  • All Publications
  • CONNECT Publications
  • Links
  • WishList
  • LA Solutions
  • Home
LA Solutions
tel: +44 1398 361 800
MstnPlatformNet

Introduction

This article is for C# developers who want to write an AddIn for MicroStation CONNECT. It is an introduction to the coding required to harvest Item Type instance data from a DGN model.

This is a complete, working example with C# source code. You can download the Visual Studio project.

Be Communities

If you want to ask questions about C# development for MicroStation CONNECT, post your question to the MicroStation Programming Forum.

Item Types

Item Types arrived with MicroStation CONNECT. They enable you to define a library of schemas. Each schema defines an Item Type and its properties. It's analogous to a table in a relational database. Read more about Item Types in MicroStation Help.

Once you defined an Item Type you can attach it to a DGN element, model or file. Once attached, it becomes an instance where you assign values to each property of the Item Type. Use MicroStation tools to examine the properties of an Item Type instance attached to a DGN element.

Item Instances

Typically, you will assign instances of an Item Type to multiple DGN elements. Perhaps you will want to harvest data about those instances for whatever purpose. One example is to create a Report. Alternatively, you might want to perform some task in MicroStation using those data or use the harvested data to write, say, an HTML or XML file.

This article is for MicroStation developers, and assumes that you want to harvest Item Type instance data programmatically. It's a guide, and the accompanying Visual Studio project is intended to help you get started with Item Types rather than to provide a useful tool.

Namespaces

MicroStation .NET code lives in the Bentley namespace, or a namespace within the scope of Bentley. In this example we're using classes and methods in the following namespaces …

  • Bentley.MstnPlatformNET
  • Bentley.DgnPlatformNET
  • Bentley.DgnPlatformNET.Elements
  • Bentley.DgnPlatformNET.DgnEC
  • Bentley.EC.Persistence.Query
  • … and possibly one or two others

You'll find the DLLs associated with those namespaces in the ..\MicroStation\assemblies folder.

ItemInstanceCollector C# Project

The Item Instance Collector is a Visual Studio 2015 project (you can also use Visual Studio 2017 to open it). The project builds into a modest MicroStation AddIn (DLL). It provides a command table for the AddIn, and shows how to …

  • Get an ECSchema object for your Item Type
  • Collect instances of that Item Type
    • An instance is the collection of Item Type property data attached to a DGN element
  • Enumerate the instance collection
  • Extract data from the instance
  • Get the associated DGN element

Get your Item Type Schema

Use MicroStation key-in command ECX LIST to see a list of EC Schemas, including Item Type schemas, in MicroStation's Message Center.

In order to find instances of your Item Type programmatically you need a schema object. To get a schema object, you need to ask the EC manager for a schema by name.

What is the name of your Item Type schema? Here you will encounter a hurdle created by Bentley Systems: your Item Type schema name is not enough! You must prefix the name with DgnCustomItemTypes_. For example, the schema name of the AreaAnnotator application is AreaAnnotator_1_0, but for the EC manager to find it I must change it to DgnCustomItemTypes_AreaAnnotator_1_0. Here's a function that does that for you …

public static string ComposeItemTypeSchemaName(string name)
{
  StringBuilder s = new StringBuilder();
  s.AppendFormat("DgnCustomItemTypes_{0}", name);
  return s.ToString();
}

Using that decorated schema name, you can ask the EC manager to find your schema …

static public IECSchema GetSchema(string schemaName)
{
  DgnFile file = Session.Instance.GetActiveDgnFile();
  bool IncludeAttachments = true;
  FindInstancesScope scope = FindInstancesScope.CreateScope(file,
                   new FindInstancesScopeOption (DgnECHostType.All, !IncludeAttachments));
  String internalSchemaName = ComposeItemTypeSchemaName (schemaName);
  IECSchema schema = DgnECManager.Manager.LocateSchemaInScope(scope, internalSchemaName, 1, 0, SchemaMatchType.Latest);
  return schema;
}

Create an ECQuery

The EC manager finds instances by executing a query . A query requires a scope, which informs the EC manager where to search. In this example the scope of the query is DgnECHostType.Element, and we may choose to search only the active DGN model, or that model plus its attachments.  …

DgnFile file = Session.Instance.GetActiveDgnFile();
bool IncludeAttachments = true;
FindInstancesScope scope = FindInstancesScope.CreateScope(file,
                   new FindInstancesScopeOption(DgnECHostType.Element, !IncludeAttachments));

The query wants a list of one or more EC classes, which we find using function GetSearchClasses(schemaName) …

public static IECClass[] GetSearchClasses (string schemaName)
{
    List<IECClass> classes = new List<IECClass> ();
    IECSchema schema = GetItemTypeSchema(schemaName);
    if (null == schema)
      return classes.ToArray ();

    foreach (IECClass ecClass in schema.GetClasses())
    {
	  classes.Add(ecClass);
    }
    int nClasses = schema.ClassCount;
    return classes.ToArray();
}

Collect Instances

With a list of EC classes, we can ask the DgnECManager to query a scope to find DGN elements tagged with Item instances belonging to that class. To find DGN elements, the scope we want is DgnECHostType.Element. The result of the query is an DgnECInstanceCollection, which implements IEnumerable<IDgnECInstance>. We could return just that IEnumerable, but I've chosen to convert it to IQueryable<IDgnECInstance> because that gives us greater flexibility subsequently …

public static IQueryable<IDgnECInstance>  GetInstances(IECClass [] classes, string schemaName, bool includeReferences)
{
    ECQuery query = new ECQuery(classes);
    query.SelectClause.SelectAllProperties = true;
    DgnECManager manager = DgnECManager.Manager;
    DgnFile file = Session.Instance.GetActiveDgnFile();
    FindInstancesScope scope = FindInstancesScope.CreateScope(file,
                                  new FindInstancesScopeOption(DgnECHostType.Element, includeReferences));
    DgnECInstanceCollection instances = manager.FindInstances(scope, query);
    return instances.AsQueryable();
}

Returning a IQueryable<IDgnECInstance> lets you enumerate the results directly or compose a LINQ query.

Find Item Instances in Cells

MicroStation developer John Drsek asked: It seems like if your item type instance is on an element thats inside a cell it isn't returning that in the query. Any way to get this query to return all instances? Jan Šlegr responded with this suggestion: I guess to set FindInstancesScopeOption.SearchPublicChildren property.

In the context of the example above, that would be something like …

FindInstancesScope scope = FindInstancesScope.CreateScope(file,
                                  new FindInstancesScopeOption(DgnECHostType.Element, includeReferences));
scope.SearchPublicChildren = true;
DgnECInstanceCollection instances = manager.FindInstances(scope, query);

Enumerate Results

Here's the simplest way to examine the list of IDgnECInstance returned by DgnECManager.FindInstances …

foreach (IDgnECInstance instance in instances)
{
  ... do something with instance
}

The IQueryable<IDgnECInstance> lets you compose a more complex query using LINQ.

Examine Each Instance

An instance has a number of properties. You can obtain a property reference using an indexer (instance ["prop_name"]) but that requires you to know the name (also known as an access string) of each property. More generally, you want to enumerate those instances. An IECInstance is an IEnumerable<IECPropertyValue>, which makes it simple to enumerate …

foreach (IDgnECInstance instance in instances)
{
    s.Clear();
    s.AppendFormat("Instance [{0}]", ++i);
    MessageCenter.Instance.ShowMessage(MessageType.Debug, s.ToString(), s.ToString(), MessageAlert.None);

    int j = 0;
    foreach (IECPropertyValue value in instance)
    {
      s.Clear();
      s.AppendFormat("Property [{0}] name '{1}' value={2}", ++j, value.Property.Name, value.StringValue);
      MessageCenter.Instance.ShowMessage(MessageType.Debug, s.ToString(), s.ToString(), MessageAlert.None);
    }
}

Get a DGN Element from an Instance

Often you will need to refer to the DGN element to which the Item instance is attached. It's the simplest code in this example …

Element element = instance.Element;

Commands

This MicroStation AddIn has a small command table, in file Commands.xml. The command handlers are in class KeyinCommands. You can key-in the commands below in MicroStation's key-in dialog. Commands are not case-sensitive …

Instance Collector Command Table
Command Option Comment
ITEMTYPES HARVEST Library Name Harvest Item Type instances
ITEMTYPES LIBRARIES List Item Type libraries

ECX Commands

Don't forget MicroStation commands starting with ECX. These provide information about EC schemas. For example, ECX SCHEMA LIST writes a list of EC schema names to the Message Center.

After keying-in one of the above commands, observe MicroStation's Message Center. Make sure that the debug option is enabled (right-click in the Message Center to see its options). You will see a list of the instance data discovered.

Acknowledgements

My thanks go to Jan Šlegr, a frequent contributor to the MicroStation Programming Forum, and Paul Connelly, a Bentley Systems developer. They both offer indispensible nuggets of advice in response to questions posted to the MicroStation Programming Forum. They helped to demystify the MstnPlatformNET API and provided hints that enabled me to develop the Item Instance Collector and write this article.


Download

Download the Item Instance Collector Project

You can download the Item Instance Collector Visual Studio project. The project was built using Visual Studio 2015 and .NET Framework 4.6.1 as required by MicroStation CONNECT after Update 5.

The project is complete: it includes all source code, the command table XML file, the Visual Studio solution file and is set up to build a DLL. The DLL is placed in your ..\MicroStation\mdlapps folder. It's similar, in that respect, to the .NET examples delivered with the MicroStation CONNECT SDK.

Build the project, which will place file ItemInstanceCollector.DLL in your ..\MicroStation\mdlapps folder. Start MicroStation and open the key-in window (from the Utilities ribbon group). Key-in
mdl load ItemInstanceCollector
You should see a message confirming that the application is loaded.

Questions

Post questions about MicroStation programming to the MicroStation Programming Forum.


Bentley Technology Partner

Trademarks

All trademarks are acknowledged. Trademarks may be registered in some jurisdictions.
e-mail Contact LA Solutions using this enquiry form.

Home
Home
Updated on 16-Apr-2020 Copyright © 2019…2025 Jon Summers