I have this:
using (FileLevelCache levelCache = ActiveDgnFile.GetLevelCache()) { LevelHandleCollection levelHandles = levelCache.GetHandles(); foreach (LevelHandle level in levelHandles) { if (level.Name.EndsWith(" P") || level.Name.EndsWith(" L")) {levelCache.RemoveLevel(null, level); levelCache.Write(); } } }
But it dont remove the levels. I think I need to remove the elements assosiated with the levels before removing the levels. But I dont know how...
Can anyone help?
Samuel Wiklund said:I need to remove the elements assosiated with the levels
Enumerate the DGN elements of a DGN model. Here's a C# example.
For each element, if it's graphical, get its level. Compare the level name with your criteria. Remove each element that passes your filter.
Regards, Jon Summers LA Solutions
using (FileLevelCache levelCache = ActiveDgnFile.GetLevelCache()) { foreach (DgnModel dgnModel in ActiveDgnFile.GetLoadedModelsCollection()) { ModelElementsCollection elementsCollection = dgnModel.GetGraphicElements(); LevelHandleCollection levelHandles = levelCache.GetHandles(); foreach (LevelHandle level in levelHandles) { if (level.Name.EndsWith(" P") || level.Name.EndsWith(" L")) { foreach (Element el in elementsCollection) { if (level.LevelId == el.LevelId) { el.DeleteFromModel(); } } levelCache.RemoveLevel(null, level); levelCache.Write(); } } } }
Now I have this where I compare levelID. I think this might work, what do you think?
For some reason i did this element removed, but all others with the ending of " P". So I thought It might depends of the type.
Samuel Wiklund said:So I thought It might depends of the type.
Yes, but not "level type" (which does not exist), but element type.
I recommend:
Regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Thank you so much for your time helping me understand.
Is it something to do with the Properties of the element thats "Not Modified"?
It worked to connect the element ID with the ID of the level to delete for simple lines but not for solids.
Maybe there is a better way to do the if-sentens to match the levels with the elements.
Samuel Wiklund said:Is it something to do with the Properties of the element thats "Not Modified"?
Again, lack of knowledge (that cannot be substituted by discussions, but solved only by some training).
Modified is an element property, showing whether it was modified (at least once) from time it was created.
Samuel Wiklund said:Maybe there is a better way to do the if-sentens to match the levels with the elements.
There is no better way, but the mandatory condition is you must understand how DGN format is designed and how API works. I wrote several times you must analyze, what Element (sub)class is returned, when SmartSolid is found, and also what ElementID:
So you must analyze what elements are iterated and adapt the evaluation accordingly to their types. Because complex headers have no element, you must decide what it means "SmartSolid is in particular level" (e.g. all elements/content are in the same level) and to write proper code.
Of course, you can use workaround and to use key-in to delete specific level.
With regards,
One more questing.
foreach (var dgnFilePath in dgnFiles) { using (DgnDocument targetDgnDocument = DgnDocument.CreateForLocalFile(dgnFilePath)) using (DgnFileOwner dgnFileOwner = DgnFile.Create(targetDgnDocument, DgnFileOpenMode.ReadOnly)) { dgnFileOwner.DgnFile.LoadDgnFile(out StatusInt statusInt); DgnFile dgnFile = dgnFileOwner.DgnFile; DgnModel dgnModel = dgnFile.LoadRootModelById(out StatusInt loadDetails, dgnFile.DefaultModelId); ActiveDgnFile.CreateNewModel(out DgnModelStatus error, dgnModel.ModelName, DgnModelType.Normal, true, dgnModel); ModelId newDgnModelId = ActiveDgnFile.FindModelIdByName(dgnModel.ModelName); DgnModel newDgnModel = ActiveDgnFile.LoadRootModelById(out StatusInt errorDetails, newDgnModelId); DgnFile.CopyModelContents(newDgnModel, dgnModel); } }
I have this to create my dgn-file with all the models from a folder containing several dgn-files and it works.
But i would like to iterate through all models, activate them and remove levels ending with " V".
Something like this:
ModelIndexCollection models = dgnFile.GetModelIndexCollection(); foreach (ModelIndex model in models) { //Delete the levels in the model... //maybe with keyin? like: Session.Instance.Keyin("level element delete \"* V\"") }
Or do you have any suggesting?
My goal is to create a cell-library with just models without the levels ending with " V"
And also a cell-library with just models ending with " V". So 2 different cell-library.
Samuel Wiklund said: i would like to iterate through all models, activate them and remove levels ending with " V".
Jan mentioned earlier that levels belong to a DGN file, not to any particular model.
Samuel Wiklund said:My goal maybe with keyin? like: Session.Instance.Keyin("level element delete \"* V\"")
Session.Instance.Keyin("level element delete \"* V\"")
Lazy idea! With .NET you have good access to MicroStation internals. Get the level cache and enumerate its contents, removing those you don't want.
Hi Samuel,
please respect the the forum best practice. This discussion has become a bit chaotic and fuzzy in my opinion.
Samuel Wiklund said:One more questing.
When you have new question, ask in a new post to do not mix different topics.
Samuel Wiklund said:I have this to create my dgn-file with all the models from a folder containing several dgn-files and it works.
I am not sure why it is posted and how it relates to this discussion.
Samuel Wiklund said:But i would like to iterate through all models, activate them and remove levels ending with " V".
That's completely another problem, not related anyhow to removing levels!
Samuel Wiklund said:Or do you have any suggesting?
Because there is a lack of basic MicroStation and DGN format features and also limited knowledge of MicroStation API, I would recommend to do everything manually. It would require a couple of minutes per file, no more.
Maybe a workaround would be to iterate throigh all models and drop the smart solids so they are not longer cell represented.
But I have a questing. I know how to send keyin with the API (Session.Instance.Keyin()), but can I also send command?
Samuel Wiklund said:I know how to send keyin with the API (Session.Instance.Keyin()), but can I also send command?
Session.EnqueueKeyin() Session.EnqueueCmd()
See MstnPlatformNet help.
The problem with EnqueueCmd is that it requires a ULong cmdNum (command number). As far as I know, command numbers are neither documented nor supplied for .NET developers. Perhaps Robert Hook can advise?
EnqueueCmd
ULong cmdNum
Jon Summers said:The problem with EnqueueCmd is that it requires a ULong cmdNum (command number).
But how often command number is required to be used? Classic funkcionality is accessible using key-i s, new one sometimes as Named command, which can also be invoked by key-in.
Hi Jon Summers,
Most often, if a key-in command is known and exists it can and should be the preferred and most easily maintainable method used.
If an app needs/requires to create an input queue command from scratch or partially for key-in purposes then it is appropriate to identify, create and assign specific CMDNUM identifiers (UInt16); some (but certainly not all) are published and can be found in the developer shell, like:
C:\Program Files\Bentley\MicroStationCONNECTSDK\examples>sdkinc C:\Program Files\Bentley\MicroStationCONNECTSDK\include>s "^#define.CMD_" *
Thank you and HTH,Bob