Select to view content in your preferred language

Question regarding GraphicsLayer.Graphics.Contains

2668
5
Jump to solution
06-28-2013 12:07 AM
JohanCarlsson
Regular Contributor
Hi!

I've created an add-in to query FeatureLayers and ArcGISDynamicMapServiceLayers.
Querying the different kinds of layers works great, but I've run into a problem and I can't seem to find a solution.

When the user queries a layer based on certain criteria, I bind the returned FeatureSet to a datagrid. The user can then select which rows they want to display in the map by marking them in the datagrid and then clicking a button that adds them to the map (in a layer that is named the same as the queried sub layer) and zooms to the result. Clicking a Graphic object in the datagrid when it is displayed in the map also changes symbology.

When I add each Graphic to the layer, I first check if the layer already contains the graphic:
            GraphicsLayer layer = LayerExists(layerName);             if (!layer.Graphics.Contains(g))                 layer.Graphics.Add(g);


The function LayerExists checks if the selected layer name already exists, if it does, it is returned. If it doesn't exist, it is created.
If I try to add the same Graphic twice (without closing the window that the  tool opens), layer.Contains(g) works fine.
However, if I close the window, open it up again, perform the same query and try to add the same Graphic object, it adds a duplicate to that layer.

I've tried solving this by comparing geometries:
            bool layerContainsGraphic = false;             foreach (Graphic graphicInLayer in layer.Graphics)             {                 if (graphicToAdd.Geometry == graphicInLayer.Geometry)                     layerContainsGraphic = true;             }              if (!layerContainsGraphic)                 layer.Graphics.Add(graphicToAdd);

but I still encounter the same problem, layerContainsGraphic is never true. The geometries never match, even though they are identical; same WKID, same extent etc. I then tried using GetHashCode, and the geometries return different hash codes. Why is that?

I also tried comparing attribute collections, but it yields the same result as above.

Sorry for the wall of text, please tell me if something in my explanation is unclear and I'll try to be clearer.

Best regards
Johan
0 Kudos
1 Solution

Accepted Solutions
DominiqueBroux
Esri Frequent Contributor
The layers you pointed out do have an ObjectId but called 'FID'.
You could loop on the layer fields, look for a field of type OID and then use this field as Identifier.

It's not 100% guarantee but...

View solution in original post

0 Kudos
5 Replies
DominiqueBroux
Esri Frequent Contributor
Running a new query returns new instances of the features so a test on layer.Graphics.Contains doesn't detect the duplicates.

You can base your test on the objectID. By supposing the OBJECID of your feature layer is "ObjectId" you could try:
var id = g.Attributes["ObjectId"];
if (!layer.Graphics.Any(graphic => graphic.Attributes["ObjectId"] == id)) ......
0 Kudos
JohanCarlsson
Regular Contributor
Thank you for your answer Dominique!

Unfortunately I can't use your solution since I can't guarantee that this field will be included.
I have been testing my add-in against one of your sample services:
http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/Map...

This service doesn't include any objectIds, and I can't be sure that our clients services will be either. Hardcoding parameters in any way is something I'd like to avoid as much as possible. Is there any other way? Would looping through the attributes, comparing each one be a possible solution? Seems a bit inefficient.

Is there any failsafe solution to approach this?
0 Kudos
DominiqueBroux
Esri Frequent Contributor
The layers you pointed out do have an ObjectId but called 'FID'.
You could loop on the layer fields, look for a field of type OID and then use this field as Identifier.

It's not 100% guarantee but...
0 Kudos
JohanCarlsson
Regular Contributor
The layers you pointed out do have an ObjectId but called 'FID'.
You could loop on the layer fields, look for a field of type OID and then use this field as Identifier.

It's not 100% guarantee but...


Thank you, this works so far!
0 Kudos
JohanCarlsson
Regular Contributor
For anyone else that is wondering, I grabbed the ObjectIdFieldName from the FeatureSet returned from the query and checked if any graphic on the currently selected layer matched this attribute.

int uniqueId = Convert.ToInt32(graphicToAdd.Attributes[StaticVariables.ObjectIdFieldName]);

        private static bool LayerContainsObject(GraphicsLayer layer, int uniqueId)
        {
            foreach (Graphic g in layer)
                if (Convert.ToInt32(g.Attributes[StaticVariables.ObjectIdFieldName]) == uniqueId)
                    return true;
            return false;
        }
0 Kudos