[OPM CE Update 9 C#] : ElementPropertiesSetter is not updating the value

I worked to change the code in MDL to C#  for changing the value of Weight property of the element.

MDL (Original Code)

            if (elemDescr == NULL) return;
            //--- traverse through descriptor ------------------------------
            do
            {
                // If have a header, call us recursively 
                if (elemDescr->h.isHeader) ApplyWeightSymbology(elemDescr->h.firstElem, weight);
                // Access next descriptor in chain 
                mdlElement_getSymbology(NULL, NULL, &style, &elemDescr->el);
                if (style != 4) mdlElement_setSymbology(&elemDescr->el, NULL, &weight, NULL);
                elemDescr = elemDescr->h.next;
            } while (elemDescr);

C# implementation of above code

private void ApplyWeightSymbology(Element element, uint weight)
        {
            ChildElementCollection childElements = element.GetChildren();

            foreach(Element childElement in childElements)
            {
                ElementPropertiesGetter propertiesGetter = new ElementPropertiesGetter(childElement);
                int styleId = propertiesGetter.LineStyleId;

                if(styleId != 4)
                {
                    ElementPropertiesSetter propertiesSetter = new ElementPropertiesSetter();
                    propertiesSetter.SetWeight(weight);
                    propertiesSetter.Apply(childElement);
                    //childElement.AddToModel();
                }
            }
            /*//--- If no descriptor, return 
            if (elemDescr == NULL) return;
            //--- traverse through descriptor ------------------------------
            do
            {
                // If have a header, call us recursively 
                if (elemDescr->h.isHeader) ApplyWeightSymbology(elemDescr->h.firstElem, weight);
                // Access next descriptor in chain 
                mdlElement_getSymbology(NULL, NULL, &style, &elemDescr->el);
                if (style != 4) mdlElement_setSymbology(&elemDescr->el, NULL, &weight, NULL);
                elemDescr = elemDescr->h.next;
            } while (elemDescr);*/
        }

However this C# code does not changes the value of the Weight property, and does not generates any error either.

Regards,

Varsha 

Parents Reply Children
  • .AddToModel actually writes back the element as well and distorts the cell element, however Apply should ensure the edit by the support document but that does not happen and .ReplaceToModel (Element replace) actually replaces the element with the current one. 

    public bool Apply(Element editElement)

    I am currently looking at EditElementProperties

    public static bool EditElementProperties (Element editElement, EditProperties editObject) in PropertyContext class

    PropertyContext.EditElementProperties(Element editElement, EditProperties editObject)

    but EditProperties is an abstract class need to inherit and override its methods. Any experience of this.

  • Tried something like this, considering the nested cell elements but no change in the properties.

     private void ApplyWeightSymbology(Element element, uint weight)
            {
                IEnumerator<Element> childElements = element.GetChildren().GetEnumerator();
    
                if (!childElements.MoveNext()) return;
    
                do
                {
                    Element currentElement = childElements.Current;
    
                    if (currentElement is CellHeaderElement)
                    {
                        ApplyWeightSymbology(currentElement, weight);
                        continue;
                    }
    
                    ElementPropertiesGetter propertiesGetter = new ElementPropertiesGetter(currentElement);
                    int styleId = propertiesGetter.LineStyleId;
    
                    if (styleId != 4)
                    {
                        //EditProperties properties = null;
                        //PropertyContext.EditElementProperties(currentElement, properties);
                        ElementPropertiesSetter propertiesSetter = new ElementPropertiesSetter();
                        propertiesSetter.SetWeight(weight);
                        propertiesSetter.Apply(currentElement);
                        //currentElement.AddToModel();
                    }
    
                } while (childElements.MoveNext());
               
            }

  • You need to rewrite the outermost header of the cell or complex element after making the modifications. propertiesSetter.Apply() modifies the current child element but doesn't persist the change.

     
    Regards, Jon Summers
    LA Solutions

  • ElementPropertiesSetter.Apply should ensure the edit by the support document but that does not happen

    You've misunderstood the admittedly terse documentation.  That method edits an Element but doesn't rewrite it.  Use this idiom to rewrite an Element...

    void RewriteElementExample (Element elToModify)
    {
      DgnModel model = Session.Instance.GetActiveDgnModel();
      Element original = model.FindElementById (elToModify.ElementId);
      ... do some work with elToModify
      elToModify.ReplaceInModel (original);
    }
    

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    Upon the suggested, the code worked as follows for me, when I made the changes directly on the element.

                    uint WEIGHT_ZERO = 0, WEIGHT_THREE = 3;
                    uint sweight = 1000;
                    int materialByOther = 0;
                    
                    IntPtr elementRef = element.GetNativeElementRef();
                    Element originalelement = Element.GetFromElementRef(elementRef);
    
                    ElementPropertiesGetter propertiesGetter = new ElementPropertiesGetter(element);
                    LevelId levelId = propertiesGetter.Level;
    
                    LevelCache cache = Session.Instance.GetActiveDgnModel().GetLevelCache();
                    string name = cache.GetLevel(levelId).DisplayName;
    
                    if (string.Equals(Global.Properties.MATERIAL_BY_OTHER, name))
                    {
                        materialByOther = 1;
                    }
    
                    if (string.Equals(Global.Properties.ZERO_STRING, materialByOther.ToString()))
                    {
                        if (!string.Equals(Global.Properties.STATE_VALUE_EXISTING, state))
                        {
                            sweight = WEIGHT_ZERO;
                        }
                        else
                        {
                            sweight = WEIGHT_THREE;
                        }
                    }
    
                    int styleId = propertiesGetter.LineStyleId;
    
                    if (styleId != 4)
                    {
                        ElementPropertiesSetter propertiesSetter = new ElementPropertiesSetter();
                        propertiesSetter.SetWeight(sweight);
                        propertiesSetter.Apply(element);
                    }
    
                    element.ReplaceInModel(originalelement);

    However i want to update the symbology of certain element of the cell header, not for all, so I am updating with below code, but OPM crashes at ReplaceInModel() function. What I am missing here?

    //Function Caller
    private void UpdateSelective(){
    IntPtr elementRef = element.GetNativeElementRef();
    Element originalelement = Element.GetFromElementRef(elementRef);
    
    ApplyStyleSymbology(elementRef, 2);
    
    // Crashing Here
    element.ReplaceInModel(originalelement);
    }
    
    // Function Callee
    private void ApplyStyleSymbology(IntPtr elementRef, int style)
            {
                Element element = Element.GetFromElementRef(elementRef);
                IEnumerator<Element> childElements = element.GetChildren().GetEnumerator();
    
                //if (!childElements.MoveNext()) return;
    
                while (childElements.MoveNext())
                {
                    Element currentElement = childElements.Current;
    
                    if (currentElement.ElementType != MSElementType.CellHeader)
                    {
                        ElementPropertiesGetter propertiesGetter = new ElementPropertiesGetter(currentElement);
                        int styleId = propertiesGetter.LineStyleId;
                        LineStyleParameters parameters = propertiesGetter.LineStyle;
                        MSElementType type = currentElement.ElementType;
    
                        if (!(type == MSElementType.BsplineCurve || type == MSElementType.BsplineKnot ||
                             type == MSElementType.BsplinePole || type == MSElementType.Curve))
                            if (styleId != 4)
                            {
                                ElementPropertiesSetter propertiesSetter = new ElementPropertiesSetter();
                                propertiesSetter.SetLinestyle(style, parameters);
                                propertiesSetter.Apply(currentElement);
                            }
                    }
    
                    if (currentElement.ElementType == MSElementType.CellHeader)
                    {
                        IntPtr currentElementRef = currentElement.GetNativeElementRef();
                        ApplyStyleSymbology(currentElementRef, style);
                    }
                } 
            }

     Regards,

    Varsha

  • OPM crashes at ReplaceInModel()
    private void UpdateSelective()
    {
    	IntPtr elementRef = element.GetNativeElementRef();
    	Element originalelement = Element.GetFromElementRef(elementRef);
    
    	ApplyStyleSymbology(elementRef, 2);
    
    	// Crashing Here
    	element.ReplaceInModel(originalelement);
    }
    
    1. Why do you cross language boundaries to get a native pointer to an element?  I've already shown how to get the original element using its ID with C#.
    2. Where does variable element come from? 

     
    Regards, Jon Summers
    LA Solutions

  • Oh... I missed the parameter

    private void UpdateSelective(Element element)

    {

         ...........

    }

    I tried that by getting element from element id but that did not worked, so have to do this. Let me check one more time by getting element from element id, and applying the same code for update.

    Will soon update here.

  • the symbology of certain element of the cell header

    It sounds like nonsense (but I guess it's only "lost in translation" issue: cell header is element itself, and other elements, representing the cell content, follow.

    What I am missing here?

    I am not sure, but I think you are missing to read my answers and linked discussion carefully (plus to do at least basic search for cell + replace keywords). It is well known long term bug in NET API.

    Regards,

      Jan