[c# .net CONNECT] ApplyCustomItem crashes MicroStation.

i cant seen to figure out what im doing wrong.

my code goes and gets a item type from a dgnlib.

i then go to add the item to a given element (happens to be a text element) from posts in this community it seems i need t set the second parameter to true when creating the customitemhost which i did. i also set the second parameter in ApplyCustomItem to true to import the library if needed. but after i call ApplyCustomItem it returns null then a couple seconds later microstation crashes.not sure what im doing wrong.

CustomItemHost host = new CustomItemHost(_MainWindowViewModel.selElementData.selTextElement, true);
if (host != null)
{
    IDgnECInstance hostItemdata = host.ApplyCustomItem(xRefItemtype, true);
    if (hostItemdata != null)
    {
        return true;
    }
        else
    {
        return false;
    }
}

i get the item type from the dgnlib from a method like this...(just showing the relevant part of the code)

            BD.ItemType xRefItemtype = null;
            BD.DgnDocument dgndoc = BD.DgnDocument.CreateForLocalFile(foundDgnLib);
            fileowner = BD.DgnFile.Create(dgndoc, BD.DgnFileOpenMode.ReadOnly);
            curfile = fileowner.DgnFile;
            BD.StatusInt status = new BD.StatusInt();
            curfile.LoadDgnFile(out status);
            BD.ItemTypeLibrary itemtypesLib = BD.ItemTypeLibrary.FindByName(GlobalVars.LinkeritemTypeLibName, curfile);
            if (itemtypesLib != null)
            {
                xRefItemtype = itemtypesLib.GetItemTypeByName(GlobalVars.LinkeritemTypeName);
                bool isvalid = verifyItemType(xRefItemtype);
                if (isvalid == true)
                {//valid

                }
                else
                {//not valid
                    resultReason = "Found " + GlobalVars.LinkeritemTypeName + " ItemType, is not valid";
                    xRefItemtype = null;
                }
            }
            else
            {
            }
            //close out of dgnlib file
            try
            {
                curfile.Release();
            }
            catch (Exception)
            {
            }
            return xRefItemtype;

i get the element by letting the user select it using DgnEleemntSetTool

  • Hi John,

    I see 5 MicroStation SDK .NET examples using ApplyCustomItem where the last one uses the second parameter with a value of true and from a dgnlib.
    Do you mind comparing your code to the last example in this list to ensure all steps are being performed?

    C:\PROGRA~1\Bentley\MICROS~1\U14\examples>s ApplyCustomItem  *.cs
    Annotations\DescribeElementExample\SelectItemTypesForm.cs:160: if(null == m_itemHost.ApplyCustomItem(itemType))
    Annotations\ManagedItemTypesExample\MainForm.cs:360:    IDgnECInstance appliedItem = m_itemHost.ApplyCustomItem(itemType);
    DgnEC\DgnECChangeEvents\ManagedExample\Keyin.cs:177:    var first = itHost.ApplyCustomItem(itpFirst);
    DgnEC\DgnECChangeEvents\ManagedExample\Keyin.cs:178:    var second = itHost.ApplyCustomItem(itpSecond);
    DgnEC\SymbolProviderExample\ManagedExample\NewSymbolProviderAtManaged.cs:132:  dgnECInstance = itHost.ApplyCustomItem(item);
    DgnEC\TestItemType\TestItemType\ItemTypeAddIn.cs:109:   DPN.DgnEC.IDgnECInstance item = host.ApplyCustomItem (itemType, true);

    Thank you,
    Bob



  • the examples also set the second parameter for the CustomItemHost to false. but then this post the answer says to set it to true. 

    https://communities.bentley.com/products/programming/microstation_programming/f/microstation-programming---forum/152319/connect-u8-systemcallback-setelmdscrtofilefunction-and-itemtypes/456210#456210 

    i think maybe i misunderstood the above linked post on needing to set that second parameter to true. not really to sure what thats doing. but i set it back to false to go with the examples and it still crashes.

    On further inspection. i have figured out the my itemItem that i got from the dgnlib. the second i close the dgnlib i lose that itemtype on that variable. So it appears i cant close the dgnlib until after i assign the item type to the element. i thought if i got the itemtype and stored it would be fine later. got to move code around now. ill post back in a little bit if that fixes the problem.

  • i have figured out the my itemItem that i got from the dgnlib. the second i close the dgnlib i lose that itemtype

    I believe that the Item Type library must exist in the DGN file where you plan to create Item Type instances.  As a user, you don't notice that MicroStation copies the definition from a DGNLib.  As a developer, you must copy the library from the DGNLib.

    If the Item Type library definition did not exist in the DGN file, you would be unable use that file in another workspace (e.g. a customer site) where the DGNLib was unavailable.

     
    Regards, Jon Summers
    LA Solutions

  • I believe that the Item Type library must exist in the DGN file where you plan to create Item Type instances.

    then whats the point of having the ApplyCustomItem call take a bool parameter that says import Library if required.

    so if i leave the dgnlib open (in the background) i dont crash when calling ApplyCustomItem. but it still returns null.

    Which i knew the lib gets copied in. but i didnt think i had to since there is a parameter that looks to be there for that exact reason. that part doesnt make any sense to me.

    So i have to first check the element to see if the item type is attached already, if not check the active file to see if the item type lib exists, if not go find it from the dgnlib and copy it to the active file, then go get the item type out of the lib that is now in your file, then finally attach the item type to the element. after doing all that i can confirm it works.  

    Answer Verified By: John Drsek 

  • So i have to first check the element to see if the item type is attached already, if not check the active file to see if the item type lib exists, if not go find it from the dgnlib and copy it to the active file, then go get the item type out of the lib that is now in your file, then finally attach the item type to the element. after doing all that i can confirm it works.  

    Ohhh ... no (only when you prefer to implement complicated code ;-).

    I have not enough time for any detail testing, but I wrote this code, that seems to be fine and does not require any such weird things like to copy anything explicitly. It should survive all scenarios: library in dgnlib or in active file, ItemType attached or not.

    private void Code()
    {
        const string itemTypeLibName = "In Lib03";
        const string itemTypeName = "Complex B";
    
        ItemTypeLibrary itemTypeLib = GetItemTypeLibrary(itemTypeLibName);
    
        if (null == itemTypeLib)
        {
            MessageCenter.Instance.StatusMessage = "ItemType Library not found";
            return;
        }
    
        ItemType itemType = itemTypeLib.GetItemTypeByName(itemTypeName);
    
        if (null == itemType)
        {
            MessageCenter.Instance.StatusMessage = "ItemType in located library not found";
            return;
        }
    
        DgnModel activeModel = Session.Instance.GetActiveDgnModel();
        ulong elementIdValue = 587;
        ElementId elementId = new ElementId(ref elementIdValue);
        Element element = activeModel.FindElementById(elementId);
    
        CustomItemHost itemHost = new CustomItemHost(element, false);
    
        IDgnECInstance item = itemHost.GetCustomItem(itemTypeLibName, itemTypeName);
    
        if (null == item)
        {
            MessageCenter.Instance.StatusMessage = "ItemType not attached, let's do it";
            item = itemHost.ApplyCustomItem(itemType, true);
        }
    
        if (null != item)
        {
            item["ID"].IntValue = 123456789;
            item["Name"].StringValue = "This is my name";
            item["Active"].NativeValue = true;
            item.WriteChanges();
            MessageCenter.Instance.StatusMessage = "Values filled";
        }
        else
        {
            MessageCenter.Instance.StatusMessage = "Something is wrong";
        }
    }
    
    private ItemTypeLibrary GetItemTypeLibrary(string name)
    {
        DgnFile activeDgnFile = Session.Instance.GetActiveDgnFile();
        ItemTypeLibrary itemTypeLib = ItemTypeLibrary.FindByName(name, activeDgnFile);
    
        if (null != itemTypeLib)
        {
            return itemTypeLib;
        }
    
        DgnLibIterator iterator = new DgnLibIterator(DgnLibSelector.ElementStyles);
    
        foreach (DgnFile dgnFile in iterator)
        {
            itemTypeLib = ItemTypeLibrary.FindByName(name, dgnFile);
    
            if (null != itemTypeLib)
            {
                return itemTypeLib;
            }
        }
    
        return null;
    }

    I guess it would be possible to simplify it even more, but well ... not enough time ;-)

    With regards,

      Jan

    Answer Verified By: John Drsek 

  • thanks Jan,

    my initial code in this post is doing relatively the same thing your code is doing. So dont know why it was crashing for me. ill test your code to verify but i already wrote it the long process i described and thats working soo ill probably keep it to that. ill post back here with my results of testing your code. 

  • my initial code in this post is doing relatively the same thing your code is doin

    Not quite ;-)

    The difference (if I remember right) is that you iterate / open / load dgnlib files yourself. My code pass this responsibility to MicroStation API. It keeps dgnlib files opened in "a minimum mode", as they are used (and opened and control cache loaded) by MicroStation already.

    With regards,

      Jan