I want to get a .NET Element from a COM Element...
Element
using Bentley.DgnPlatformNET; using Bentley.DgnPlatformNET.Elements; using Bentley.MstnPlatformNET; using BCOM = Bentley.Interop.MicroStationDGN;
Element GetElementFromComElement (BCOM.Element oElement, bool addToModel) { if (addToModel) { BCOM.Application app = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp; app.ActiveModelReference.AddElement(oElement); } IntPtr pointer = (IntPtr)oElement.MdlElementRef(); Element el = Element.GetFromElementRef(pointer); return el; }
If I call the above function with addToModel True, it works. If I call the function with addToModel False, it returns a null. But I don't want to write the COM element to file: I want an in-memory .NET Element. What's going on?
addToModel
I've marked this thread as solved, because a work-around exists. The question: 'Can we obtain a .NET Element from COM?' remains unanswered.
Jon Summers said:if I want to create a .NET element in memory from a COM source
Just for curiosity, in what situation you need to do this conversion?
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Jon Summers said:What I could use is a .NET Element constructor that takes an MdlElementDescriptor, but unfortunately doesn't exist.
MdlElementDescriptor
It seems it exists internally, in Bentley.DgnPlatform.ElementHandle constructor accept element descriptor (I guess it's wrapper around EditElementHandle constructor). But it's true it's not available publicly.
For now, it seems the only way is to write own wrapper / convertor, similar to what is described in the linked blog about C++/CLI :-(
Regards,
Jan Šlegr said: in what situation you need to do this conversion?
Principally to solve the missing .NET create cell instance requirement. That is, use COM CreateCellElement2() and get a .NET CellHeaderElement.
CreateCellElement2()
CellHeaderElement
It works once the cell is added to a model. But I want to show the cell in dynamics, and therefore need an in-memory object.
Regards, Jon Summers LA Solutions
Jon Summers said:Principally to solve the missing .NET create cell instance requirement.
I agree it's the issue not solved by Bentley for very long time (and asked many times).
When looking into documentation, even in C++ API it's not possible to use handler to load a cell from library, but "old" mdlCell_ functions have to be used.
Jon Summers said:But I want to show the cell in dynamics, and therefore need an in-memory object.
It looks like such simple and valid requirement leads to complex transaction: When displayed in dynamics, the cell and all relevant styles + levels should be loaded (but not stored in active DGN yet). And when placed, also attached data (XAttributes...) have to be copied from the cell library.
Jan Šlegr said:I agree it's the issue not solved by Bentley
The InterOp route suggested by Yongan.Fu in his csAddIn project works well. I've attached some code that implements both a normal cell placement tool and a shared cell placement tool. Both call VBA COM classes and methods.
To my pleasant surprise, it's possible, in a C# implementation, for a class to inherit from a COM interface (IPrimitiveCommandEvents)...
IPrimitiveCommandEvents
class PlaceSharedCellComTool : IPrimitiveCommandEvents { }
That gives us the state engine provided by COM, which works just as it does in VBA.
PlaceCellExample.zip
Answer Verified By: Jon Summers
Jon Summers said:To my pleasant surprise
Honestly, I think there is no reason why to be surprised. It's a standard way how C# works.
Jon Summers said:for a class to inherit from a COM interface (IPrimitiveCommandEvents)...
I don't want to be a stickler for technical accuracy, but when Bentley.Interop.MicroStationDGN.dll assembly is referenced and used, it's not COM interface in fact (which is available in ustation.dll), but classes already transformed to NET API (which is the only reason why COM Interop exists ;-) So all NET features are supported (in contrast with direct referencing and accessing COM library).
Jon Summers said:The question: 'Can we obtain a .NET Element from COM?' remains unanswered.
It certainly can but needs a lots of tricks. I am asking my team member to write a such blog. Waiting for days.
Yongan.Fu said: I am asking my team member to write a such blog.
It would be great, thanks!
On the other hand, to add "load a cell from library" and "place a cell from library" functionality to NET API would be even much better, because my feeling is that 99% of all questions "COM/Interop vs new NET API" is about impossibility to work and place cells in libraries.
Below Chinese wiki article elaborates the conversion between COM Element and .NET Element by using C#.
https://communities.bentley.com/communities/other_communities/bdn_other_communities/b/bdn-blog/posts/element