4

I'm looping through the IElement objects in an IGraphicsContainer and need to get the properties of another IElement by name.

I thought I could write a getElementByName function to loop through an IGraphicsContainer and return the IElement, but as soon as I call this function, the state of the IGraphicsContainer of the main loop changes.

How can I get an IElement by name while looping through an IGraphicsContainer?

Edit: While looping through one GraphicsContainer, I'm calling a getElementByName function which itself loops through a GraphicsContainer. When the function calls GraphicsContainer.Reset(), the outer loop GraphicsContainer is also reset. How do I stop this?

Edit: hnasr came up with a very good solution in VB. Here it is in C#

using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Carto;

namespace FooBar
{
    public class dotNetGraphicsContainer : Dictionary<string, IElement>
    {
        public void Refresh(IMxDocument pMXDoc)
        {
            base.Clear();
            IGraphicsContainer pGC = pMXDoc.ActiveView.GraphicsContainer;
            pGC.Reset();
            IElement pElement = pGC.Next();

            while (pElement != null)
            {
                IElementProperties pElementProp = (IElementProperties)pElement;

                if (!this.ContainsKey(pElementProp.Name))
                    this.Add(pElementProp.Name, pElement);

                pElement = pGC.Next();
            }
        }
    }
}
  • You may want to add more details to your problem, as there might be another way to do it without nested loops. – hnasr Feb 13 '14 at 12:16
3

The only way I see this possible is through populating your own list or dictionary. In fact, it is more efficient to use dictionaries if you are planning to frequently access the graphics.

Create the following class. This will be a dictionary version of your graphics container. The key is the name, the value is IElement. You can uniquely fetch a graphic using the key.

Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.Carto


Public Class dotNetGraphicsContainer
    Inherits Dictionary(Of String, IElement)

    ''' <summary>
    ''' Refresh the new list and bring the updated graphics
    ''' </summary>
    ''' <param name="pMxDoc"></param>
    ''' <remarks></remarks>
    Public Sub Refresh(ByVal pMxDoc As IMxDocument)
        MyBase.Clear()
        Dim pGC As IGraphicsContainer = pMxDoc.ActiveView.GraphicsContainer
        pGC.Reset()
        Dim pElement As IElement = pGC.Next

        Do Until pElement Is Nothing
            Dim pElementProp As IElementProperties = pElement

            If ContainsKey(pElementProp.Name) = False Then
                Add(pElementProp.Name, pElement)
            End If

            pElement = pGC.Next
        Loop

    End Sub


End Class

This is how you use the class

Public Sub Main()

    Dim pGC As New dotNetGraphicsContainer()
    pGC.Refresh(MxDocument)

    'loop through the graphic container
    For Each e As KeyValuePair(Of String, IElement) In pGC
        'get element by name 

        Dim pElement As IElement = pGC("element name")
        'do whatever.
    Next

End Sub

Make sure to call "Refresh" every time you want to get a fresh copy of graphics from the map. You can loop on this structure as many times as you want without worrying about reset.

Hope that helps.

  • This is a good example. I tried it on one of my sample map layouts. Unfortunately some of the elements aren't named, so they simply aren't included in the dictionary. – Mattropolis May 30 '17 at 6:00
2

would this work? or maybe you need to call IGraphicsContainer.Reset() before looping.

public IElement GetElementByName(IMap map, string name)
{
   IGraphicsContainer graphicsContainer = (IGraphicsContainer)map;
   IElement element = graphicsContainer.Next();
   IElement retElement = null;

   while (element != null)
   {
      IElementProperties elemProps = (IElementProperties)element;
      if (elemProps.Name == name)
      {
         retElement = element;
         break;
      }           
       element = graphicsContainer.Next();
    }

    return retElement;
}
  • It doesn't work for me, I am effectively calling a similar function getElementByName(IMxDocument mxdoc, string elementName) from within a graphicsContainer loop. Whenever I call graphicsContainer.Reset() in my getElementByName function, it also resets the main graphicsContainer as well. – John Feb 13 '14 at 2:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.