Hi
I am trying to read the value of an existing Item and make some changes to it and then replace my instance with the new edited version. I am using InstanceReadStatus iReadStatus = wipInstance.ReadFromXmlString(iecInstancePtr, xml6.c_str(), *ecReadContextPtr); to read and ecEnabler->ScheduleReplaceInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, *elemRef->GetDgnModelP(), ehandle, uLocalId);//*ACTIVEMODEL, ehandle, uLocalId); to replace the instance. So far with no luck on the replacement part :-(
My code looks like this:
if (opdater)
{
ECN::ECSchemaPtr pSchema;
std::wstringstream xml5;
boost::property_tree::xml_parser::write_xml_element(xml5, {}, pt, -1, xml_writer_settings<wptree::key_type>{});
Bentley::WString xml6 = xml5.str().c_str();
////xmlInstanceApi.UpdateInstance(status, Bentley::WString(xml3.c_str()));
///// Først finder vi schema på instansen ved at finde schema på class'en
WString wsClass = instP->GetClass().GetName();
if (wsClass.length() > 0)//|| wsClass.CompareTo(L"ECQUERY_PROCESS_SearchAllClasses"))
{
DgnECManagerR ecMan = DgnECManager::GetManager();
SchemaInfo schemaInfo(ECN::SchemaKey(wsClass.GetWCharCP(), 1, 0), *ISessionMgr::GetActiveDgnFile());///L"skelpunkt1", 1, 0), *dgnfilePtr);
pSchema = ecMan.LocateSchemaInDgnFile(schemaInfo, ECN::SchemaMatchType::SCHEMAMATCHTYPE_LatestCompatible);
//if (!intName.IsNullOrEmpty(intName.GetWCharCP()))
// ECN::ECClassCP pVolClass = pSchema->GetClassCP(intName.c_str());//(L"Sofa").c_str
}
ECInstanceReadContextPtr ecReadContextPtr = schemaManager.CreateECInstanceReadContext(*pSchema, *ISessionMgr::GetActiveDgnFile());
// Find the ECEnabler that is handling a PropertiesClass in the dgn file.
// Findes højere oppe i koden DgnECInstanceEnablerP ecEnabler = DgnECManager::GetManager().ObtainInstanceEnabler(instP->GetClass(), *ISessionMgr::GetActiveDgnFile());//*ecClass, *ISessionMgr::GetActiveDgnFile());
//Gets a StandaloneECInstance to be used as a template when creating new persistent ECInstances.
StandaloneECInstanceR wipInstance = ecEnabler->GetSharedWipInstance();
/// Læse xml-streng til instance
/// Lav en instancepointer, som vi kan knytte data fra xml'en til
IECInstancePtr iecInstancePtr;
/// Læse xml-streng til instance
InstanceReadStatus iReadStatus = wipInstance.ReadFromXmlString(iecInstancePtr, xml6.c_str(), *ecReadContextPtr);
if (iReadStatus != INSTANCE_READ_STATUS_Success)
OutputDebugString(L"Create Text - Oh no - der er noget galt med wipInstanceReadFromXmlString");
/// Opret en PropertiesClass instance på det element vi vil opdatere
DgnElementECInstancePtr s_propertiesClassInstance = nullptr;
DgnElementECInstanceCP elemInstance = instP->GetAsElementInstance();
UInt32 uLocalId = elemInstance->GetLocalId();
DgnECInstanceStatus dgnECInstancestatus = ecEnabler->ScheduleReplaceInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, *elemRef->GetDgnModelP(), ehandle, uLocalId);//*ACTIVEMODEL, ehandle, uLocalId);///->CreateInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, eh);
if (dgnECInstancestatus == DGNECINSTANCESTATUS_Success)
{
ehandle.ReplaceInModel(ehandle.GetElementRef());
OutputDebugString(L"WriteChanges er: SLÅET FRA");// +sWrite);
}
else
OutputDebugString(L"Fejl i oprettelsen af instance, fejlkode: " + dgnECInstancestatus);
}
} ///for each (DgnECInstancePtr instP in instanceIter)
I am doing something wrong. Reading the xml seems to be ok:
(here I ill add a screendump shortly)
And the ScheduleReplaceInstanceOnElement also seem to be ok, but nothing happens. Am I supposed to rewrite either the element or the instance or?
(here I ill add a screendump shortly)
I have tried a million things but so far with no luck. I could of course also delete the instance and then rewrite it.
if (opdater)
{
ECN::ECSchemaPtr pSchema;
std::wstringstream xml5;
boost::property_tree::xml_parser::write_xml_element(xml5, {}, pt, -1, xml_writer_settings<wptree::key_type>{});
Bentley::WString xml6 = xml5.str().c_str();
////xmlInstanceApi.UpdateInstance(status, Bentley::WString(xml3.c_str()));
///// Først finder vi schema på instansen ved at finde schema på class'en
WString wsClass = instP->GetClass().GetName();
if (wsClass.length() > 0)//|| wsClass.CompareTo(L"ECQUERY_PROCESS_SearchAllClasses"))
{
DgnECManagerR ecMan = DgnECManager::GetManager();
SchemaInfo schemaInfo(ECN::SchemaKey(wsClass.GetWCharCP(), 1, 0), *ISessionMgr::GetActiveDgnFile());///L"skelpunkt1", 1, 0), *dgnfilePtr);
pSchema = ecMan.LocateSchemaInDgnFile(schemaInfo, ECN::SchemaMatchType::SCHEMAMATCHTYPE_LatestCompatible);
//if (!intName.IsNullOrEmpty(intName.GetWCharCP()))
// ECN::ECClassCP pVolClass = pSchema->GetClassCP(intName.c_str());//(L"Sofa").c_str
}
ECInstanceReadContextPtr ecReadContextPtr = schemaManager.CreateECInstanceReadContext(*pSchema, *ISessionMgr::GetActiveDgnFile());
// Find the ECEnabler that is handling a PropertiesClass in the dgn file.
// Findes højere oppe i koden DgnECInstanceEnablerP ecEnabler = DgnECManager::GetManager().ObtainInstanceEnabler(instP->GetClass(), *ISessionMgr::GetActiveDgnFile());//*ecClass, *ISessionMgr::GetActiveDgnFile());
//Gets a StandaloneECInstance to be used as a template when creating new persistent ECInstances.
StandaloneECInstanceR wipInstance = ecEnabler->GetSharedWipInstance();
/// Læse xml-streng til instance
/// Lav en instancepointer, som vi kan knytte data fra xml'en til
IECInstancePtr iecInstancePtr;
/// Læse xml-streng til instance
InstanceReadStatus iReadStatus = wipInstance.ReadFromXmlString(iecInstancePtr, xml6.c_str(), *ecReadContextPtr);
if (iReadStatus != INSTANCE_READ_STATUS_Success)
OutputDebugString(L"Create Text - Oh no - der er noget galt med wipInstanceReadFromXmlString");
/// Opret en PropertiesClass instance på det element vi vil opdatere
DgnElementECInstancePtr s_propertiesClassInstance = nullptr;
DgnElementECInstanceCP elemInstance = instP->GetAsElementInstance();
UInt32 uLocalId = elemInstance->GetLocalId();
DgnECInstanceStatus dgnECInstancestatus = ecEnabler->ScheduleReplaceInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, *elemRef->GetDgnModelP(), ehandle, uLocalId);//*ACTIVEMODEL, ehandle, uLocalId);///->CreateInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, eh);
if (dgnECInstancestatus == DGNECINSTANCESTATUS_Success)
{
ehandle.ReplaceInModel(ehandle.GetElementRef());
OutputDebugString(L"WriteChanges er: SLÅET FRA");// +sWrite);
}
else
OutputDebugString(L"Fejl i oprettelsen af instance, fejlkode: " + dgnECInstancestatus);
}
} ///for each (DgnECInstancePtr instP in instanceIter)
It is this call I don't understand:
DgnECInstanceStatus dgnECInstancestatus = ecEnabler->ScheduleReplaceInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, *elemRef->GetDgnModelP(), ehandle, uLocalId);//*ACTIVEMODEL, ehandle, uLocalId);
I am finding it difficult to understand what is connected to the element and what is connected to the element-instance on the element, which also can be treated as a element (instP->GetAsElementInstance()).
Help says:
//! Schedules the replacement of an existing instance associated with an element that is identified by the localid. The element is identified by an EditElementHandle.
//! @param[out] dgnecInstance DgnECInstance that is created.
//! @param[in] wipInstance A ECN::StandaloneECInstance that was probably a "shared" instance with its memory shared with a managed ECDInstance.
//! @param[in] modelRef The modelRef to be used by the returned DgnECInstance. Typically you should pass *elementRef.GetDgnModelP().
//! The exception is if you will be using the returned DgnECInstance to create an ECRelationship to another
//! DgnECInstance that does not reside in the same DgnModel. In that case, you must pass the DgnModelRef of the
//! particular attachment that will be used by that ECRelationship. See docs for DgnECManager::CreateRelationship.
//! @param[in] eh The element on which to persist the newly-created DgnECInstance
//! @param[in] localId Identifies the existing instance to replace. Typically the xattribute id.
DGNPLATFORM_EXPORT DgnECInstanceStatus ScheduleReplaceInstanceOnElement (DgnElementECInstancePtr* dgnecInstance, ECN::IECInstanceCR wipInstance, DgnModelRefR modelRef, EditElementHandleR eh, UInt32 localId) const;
I am finding it difficult to create a good description as I honestly don't understand what it is I don't understand :-)
The code where I create an instance (which works) looks like this:
//xmlInstanceApi.CreateInstance(status, newDescr->h.elementRef, xml);
ECInstanceReadContextPtr ecReadContextPtr = schemaManager.CreateECInstanceReadContext(*pSchema, *ISessionMgr::GetActiveDgnFile());
DgnElementECInstancePtr s_propertiesClassInstance = nullptr;
/// Vi finder Class/tabel, som schema'et peger på, denne er oprettet i vores skema()-funktion
ECClassP ecClass = pSchema->GetClassP(schema.name);
if (ecClass == nullptr)
{
WString wsTemp = L"Addinstance - Ups der er noget galt med ecClass!";
OutputDebugString(wsTemp.c_str());
return;
}
/// Find the ECEnabler that is handling a PropertiesClass in the dgn file.
DgnECInstanceEnablerP ecEnabler = DgnECManager::GetManager().ObtainInstanceEnabler(*ecClass, *ISessionMgr::GetActiveDgnFile());
//Gets a StandaloneECInstance to be used as a template when creating new persistent ECInstances.
StandaloneECInstanceR wipInstance = ecEnabler->GetSharedWipInstance();
/// Lav en instancepointer, som vi kan knytte data fra xml'en til
IECInstancePtr iecInstancePtr;
/// Læse xml-streng til instance
InstanceReadStatus iReadStatus = wipInstance.ReadFromXmlString(iecInstancePtr, xml.c_str(), *ecReadContextPtr);
if (iReadStatus != INSTANCE_READ_STATUS_Success)
OutputDebugString(L"Create Text - Oh no - der er noget galt med wipInstanceReadFromXmlString");
// Opret en PropertiesClass instance på det element vi er ved at danne
DgnECInstanceStatus dgnECInstancestatus = ecEnabler->CreateInstanceOnElement(&s_propertiesClassInstance, *iecInstancePtr, ehandle);
if (dgnECInstancestatus != DGNECINSTANCESTATUS_Success)
OutputDebugString(L"Fejl i oprettelsen af instance, fejlkode: " + dgnECInstancestatus);
if (elementType == 2)
{
updateNumber();
}
} // if (schema.ecproperties.count(-1)!=0)
ElementTemplateNodePtr templateP; // ElementTemplateP templateP;
templateP = ElementTemplateUtils::GetReferencedTemplate(ehandle.GetElementRef());//temp->h.elementRef);
if (templateP != NULL) // if (SUCCESS != mdlElementTemplate_loadFromElement(&templateP, ehandle.GetElementRef(), ACTIVEMODEL))
{
MstnElementTemplateMgr::ApplyElementTemplateParams(ehandle, *templateP); // if (SUCCESS == mdlElementTemplate_applySymbology(templateP, ehandle))
if (BSISUCCESS == MstnElementTemplateMgr::ScheduleTemplateReferenceAttachment(ehandle, *templateP)) //if (SUCCESS == mdlElementTemplate_scheduleTemplateReferenceAttachment(templateP, ehandle))
ehandle.ReplaceInModel(ehandle.GetElementRef());
} // hvis templateP ikke er null
I Hope someone can push me in the right direction :-)
Best regards
Bo.