[CONNECT c++] get EC instance of itemtype on element?

    //Link to a Property on this element
	ElementId elemIdLink = ElementIDLink;
	ElementHandle elemLink(elemIdLink, pActiveModel);
	if (!elemLink.IsValid())
	{
		return false;
	}
	
	ElementECClassInfo ecClassInfo2;
	DgnECManagerR ecManager = DgnECManager::GetManager();
	ecManager.FindECClassesOnElement(elemLink.GetElementRef(), ecClassInfo2);
	//how would i loop ecClassInfo2 to find the item type i want?
	//need to figure out how to get classes
	ecManager.FindInstanceOnElement(elemLink, ecClass2); //this is wrong

trying to figure out how to do this..

I need to get the ec instance of an item type instance that is attached to an element.

I need this to add a text field to a text element via TextField::CreateForElement.

im struggling on how to do that...

  • Hi John,

    is there any specific reason, why to use generic "EC approach" when you want to work specifically with ItemType data?

    I recall it has been discussed several times, I found e.g. this discussion (but not sure whether the code is working).

    With regards,

      Jan

    Answer Verified By: John Drsek 

  • no reason, just thought that's the way I needed..

    I looked briefly at the post (about to leave for the day) how would I take that DgnECInstancePtr and get a DgnElementECInstancePtr from it to use in the

    TextField::CreateForElement method?

    Ill look more into it tomorrow

    thanks

    JD

  • I need to get the ec instance of an item type instance that is attached to an element

    This article about EC Queries may help.  It distils tips that Paul Connelly and others have given over the years.  You need to create a scope and a query before calling DgnECManager::FindInstances.

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: John Drsek 

  • Thanks Jan and Jon, wouldn't have gotten this without your help, much appreciated.

    I ended up going the way the post Jan linked to since it was simpler and to do the EC query way that Jon posted I would need to get the item type anyways to get the internal names.

    but Jon that web link is awesome, I did try it out and I will probably be using it in the future. it did show me the GetAsElementInstance method that I needed.

    here is my code for anyone its a method that takes the id to a text element and a id to the element that contains the item type instance you want to create a field for. ill probably be adding a 3rd parameter for the property name you cant the field to be linked to. but it will add a field linked to a property of the item type instance to the end of the text element.

    bool AddField(__int64 ElementIDText, __int64 ElementIDLink)
    {
    	DgnModelP       pActiveModel = ISessionMgr::GetActiveDgnModelP();
    	DgnFileP activeDgnFile = ISessionMgr::GetActiveDgnFile();
    	//Text Element to add field to
    	ElementId  elemIdText = ElementIDText; //text element
    	ElementHandle elemText(elemIdText, pActiveModel); //text element
    	if (!elemText.IsValid())
    	{
    		return false;
    	}
    	//Link to Property on this element
    	ElementId elemIdLink = ElementIDLink;
    	ElementHandle elemLink(elemIdLink, pActiveModel); //text element
    	if (!elemLink.IsValid())
    	{
    		return false;
    	}
    	EditElementHandle  eehLink(elemIdLink, pActiveModel);
    
    	//get text block (should only be one text part)
    	TextBlockPtr pTextBlock = TextHandlerBase::GetFirstTextPartValue(elemText);
    
    	//get Inst of link element itemtype 
    	ItemTypeLibraryPtr newLibrary = ItemTypeLibrary::FindByName(L"OHDOT_Linkers", *activeDgnFile);
    	if (newLibrary.IsValid())
    	{
    		ItemTypeP itemType = newLibrary->GetItemTypeByName(L"TextFieldLinker");	//nullptr if not found
    		if (itemType)
    		{
    			CustomItemHost host(eehLink);
    			DgnECInstancePtr itemInstance = host.GetCustomItem(newLibrary->GetName(), itemType->GetName());
    			if (itemInstance.IsValid())
    			{
    				DgnElementECInstanceP elementItemInstance = itemInstance->GetAsElementInstance();
    				TextFieldPtr pField = TextField::CreateForElement(*elementItemInstance, L"Values[0].ModelName", nullptr, *pActiveModel);
    				if (pField == NULL)
    				{
    					return false;
    				}
    
    				pTextBlock->AppendField(*pField); //add field to text block
    
    				//replace old textblock with new one
    				EditElementHandle  eeh(elemIdText, pActiveModel);
    				ITextEditP et = eeh.GetITextEdit();
    				T_ITextPartIdPtrVector partIds;
    				et->GetTextPartIds(eeh, *ITextQueryOptions::CreateDefault(), partIds);
    				et->ReplaceTextPart(eeh, *partIds[0], *pTextBlock);
    
    				//replace element in model
    				eeh.ReplaceInModel(elemText.GetElementRef());
    				return true;
    			}
    			else
    			{
    				return false;
    			}
    		}
    		else
    		{
    			return false;
    		}
    	}
    	else
    	{
    		return false;
    	}

    Answer Verified By: John Drsek 

  • Hi John,

    I ended up going the way the post Jan linked to since it was simpler

    probably (nearly) always, when you need to access ItemTypes data and not other type of EC data (e.g. based on custom schema created in Bentley Class Editor or EC data created by other applications), to use ItemTypes API is simpler and quicker.

    Although ItemTypes data are EC data, specialized API hides some implementation details and automates some steps, so it's not necessary to know all details how EC schemas work and how ItemTypes are implemented as particular EC schema.

    And of course, thanks for your code! :-)

    With regards,

      Jan