I've gone through all the threads I could find regarding ReplaceInModel method when it applies to elements within a cell and so far no one has provided any direction. In the code below:
TextElement origElem = (TextElement)Element.GetFromElementRef(elem.GetNativeElementRef()); TextElement t = (TextElement)elem; TextBlock tb = t.GetTextPart(id); tb.Remove(tb.CreateStartCaret(), tb.CreateEndCaret()); tb.InsertText(tb.CreateStartCaret(), newValue); if (TextReplaceStatus.Success == t.ReplaceTextPart(id, tb)) { t.ReplaceInModel(origElem); }
If the TextElement is within CellElement, the t.ReplaceInModel will crash microstation. Do I need to somehow update the CellElement? And if its a multi-level Cell, like Cell within a Cell, do I need to update the top level Cell?
Thanks.
Sure. A lot of threads report .NET API has a bug for modifying sub elements in cell. I can replicate this as well.
Two workarounds: 1.Use Interop API as below:
using BIM = Bentley.Interop.MicroStationDGN; using BMI = Bentley.MstnPlatformNET.InteropServices; public static void ReplaceInCell(string unparsed) { BIM.Application app = BMI.Utilities.ComApp; BIM.CellElement myCell = app.ActiveModelReference.GetElementByID64(583L) as BIM.CellElement; myCell.ResetElementEnumeration(); int nestDepth = 0; while(myCell.MoveToNextElement(true, ref nestDepth)) { BIM.Element tempEl = myCell.CopyCurrentElement(); if (tempEl.IsTextElement()) { BIM.TextElement oldTextEl = tempEl.AsTextElement(); BIM.Point3d org = oldTextEl.get_Origin(); BIM.Matrix3d matrix = oldTextEl.get_Rotation(); BIM.TextElement newTextEl = app.CreateTextElement1(oldTextEl, "ReplaceText", ref org, ref matrix); myCell.ReplaceCurrentElement(newTextEl); } } myCell.Rewrite(); }
2. Use C++ API.
Thanks, I guess if i use COM api, I don't really need to replace the element, you can simply iterate the subelements, update text and then rewrite them. I guess that would be my last option, but then i'm back to square one and limited text processing that COM has, I was just getting used to the NET api there...
If I choose c++ api, is there an example how to have a c++ method within your .NET project? Do I just add a cpp file and more references? this would be all new to me.
This is kind of depressing, I'm told to use NET api because its the future & COM api is old and doesn't support new features and at the same time NET api is not fully baked either and poorly documented.
Viktor_Kulik said:Is there an example how to have a C++ method within your .NET project?
Microsoft calls that either P/Invoke, if you want to call a handful of functions, or C++/CLI. You probably don't want to write much of that code, because you have to use unorthodox C++ syntax.
You can also go in the opposite direction. Here's an example of a C++ client that uses a .NET DLL.
Viktor_Kulik said:I'm told to use NET api because its the future & COM api is old
C++ is pretty good. It falls down when designing the User Interface, because standard C++ doesn't have such a thing.
Regards, Jon Summers LA Solutions
Thanks Jon, yea the C++ with .NET dll would definitely NOT be my approach, I am as green as they come in c++. and UI is important.
I think I can figure out the code part of the C++ based on all the examples, my main concern is that how do I add that file into my project? Do i need to reference? or just include the file?
HI Viktor,
Viktor_Kulik said:but then i'm back to square one and limited text processing that COM has, I was just getting used to the NET api there...
Unfortunately you hit one from several issues, still existing in NET API. There are not many of them right now, the most critical are placing cell from cell ibrary and the discussed cell content editing. Unfortunately, Bentley are not able to fix it (for unknown reason), even when requested many times for last several years.
Viktor_Kulik said:If I choose c++ api, is there an example how to have a c++ method within your .NET project?
It is standard NET Framework (not MicroStation) feature, so it's possible to find plenty of tutorials and examples on Internet. As Jon wrote, there are in general two ways:
Viktor_Kulik said:Do I just add a cpp file and more references? this would be all new to me.
It depends what way you choose:
Viktor_Kulik said:This is kind of depressing, I'm told to use NET api because its the future & COM api is old and doesn't support new features
Generally, it's true. NET API covers the most of native API (but it was never promissed it will be equal), whereas Interop (built on top of COM API) represents only a fraction of functions. But, and it was discussed many times, there are some (only a few in my opinion) situations, when COM is better.
But, as far as I remember, the clear message from Bentley alwas was "when you need complete functionality, C++ is the only recommended choice, whereas NET is better to build GUI". In my opinion it is normal that different tools, languages and APIs are used in one project, to ensure the best tool is used to solve particular requirement.
Viktor_Kulik said:and at the same time NET api is not fully baked either and poorly documented.
I must say I use typically C++ documentation + dnSpy or NET Reflector, not NET one, beause as you wrote, it is not very usefull (but, exceptions exist, and some features are described in the great detail in NET doc ;-)
Regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point