Select to view content in your preferred language

Add Feature Layer by Name?

2660
10
04-22-2011 09:37 AM
TonyThatcher
Deactivated User
I believe that I already know the answer to this.  But is it possible to add a FeatureLayer by Name, and not the Index Number? 

We are having to work off a single Map Service that will likely be adding and removing layers from the Service from time to time.  For some web applicaitons this works well because we want to display the map layers in entire Map Service.  Some web applications, we only want to display a sub-set of the service, so we are using FeatureLayers to add the layer to the Silverlight app.  The only way that I can see to do this is to use the full URL, along with the Index Number of the layer we want to add.  The problem comes if the Map Service is updated and the index numbers change.  Then what used to be, say, the city boundary, is now a layer of gas stations, or something like that. 

I'd prefer to access the layer by the Layer Name, and not an ID.  Has anyone come up with a way around this?  A function that uses the Layer Name to return the Index Number of the layer?  Then dynamically build the URL and add the layer?

Thanks!

-Tony
0 Kudos
10 Replies
by Anonymous User
Not applicable
Thats what I do. I use a method to check each LayerInfo's name, then return the LayerInfo.ID if the name matches.
0 Kudos
TonyThatcher
Deactivated User
Thanks, Michael.  I figured as much.  Any code you'd care to share, on-line or off?  I hate to recreate wheels that already exist.

-Tony
0 Kudos
by Anonymous User
Not applicable
Something like this:


 
        //C#
        //returns -1 if layer not found
        private static int GetTargetLayer(Map map, string layerName)
        {
            var retVal = -1;
            var layerCollection = map.Layers;
            
            if (layerCollection != null)
            {
                //Check only ArcGISDynamicMapServiceLayer with sublayers
                foreach (var dynamicLayer in
                    layerCollection.OfType<ArcGISDynamicMapServiceLayer>().Select(layer => layer).Where(dynamicLayer => dynamicLayer.Layers != null))
                {
                    //Check for the layer name
                    foreach (var layerInfo in dynamicLayer.Layers.Where(layerInfo => layerInfo.Name == layerName))
                    {
                        //Layer name found, return the ID
                        retVal = layerInfo.ID;
                        break;
                    }
                }
            }

            return retVal;
        }
0 Kudos
TonyThatcher
Deactivated User
Wonderful!  But you would have to be a C# guy!  No problem.  Us VB neanderthals will cope.;)
0 Kudos
by Anonymous User
Not applicable
Wonderful!  But you would have to be a C# guy!  No problem.  Us VB neanderthals will cope.;)



LOL, maybe this will be easier to translate (Linq expressions removed)

 private static int GetTargetLayer(Map map, string layerName)
        {
            var retVal = -1;

            var layerCollection = map.Layers;
            
            if (layerCollection != null)
            {
                foreach (var layer in layerCollection)
                {
                    if (!(layer is ArcGISDynamicMapServiceLayer)) continue;

                    var dynamicLayer = layer as ArcGISDynamicMapServiceLayer;

                    if (dynamicLayer.Layers != null)
                    {
                        foreach (var layerInfo in dynamicLayer.Layers)
                        {
                            if (layerInfo.Name == layerName)
                            {
                                retVal = layerInfo.ID;
                                break;
                            }
                        }
                    }
                }
            }

            return retVal;
        }
0 Kudos
TonyThatcher
Deactivated User
Finally getting back to this.  Thanks for the code, Michael.  I was able to convert it to VB.NET (below)

Private Function GetTargetLayer(ByVal Map As Map, ByVal strLayerName As String) As String

        Try
            Dim layerCollection As LayerCollection = Map.Layers
            Dim basePath As String = "http://www.co.missoula.mt.us/ArcGIS/rest/services/Atlas/Atlas/MapServer/"

            If Not (layerCollection Is Nothing) Then
                For Each lyr In layerCollection
                    If (TypeOf (lyr) Is ArcGISDynamicMapServiceLayer) Then
                        Dim dynamicServiceLayer As ArcGISDynamicMapServiceLayer = lyr
                        'Dim layerInfo As New LayerInfo
                        For Each layerInfo In dynamicServiceLayer.Layers
                            If layerInfo.Name = strLayerName Then
                                MessageBox.Show(CStr(layerInfo.ID))
                                GetTargetLayer = basePath + layerInfo.ID.ToString
                            End If
                        Next
                    End If
                Next
            Else
                GetTargetLayer = "NA"
            End If
        Catch ex As Exception
            GetTargetLayer = "NA"
        End Try

    End Function


I've attached the code to a Silverlight LeftMouseDown event to test the code and it returns the correct URL string and ID for the layer.  The next challenge is, how do I get the bind this string to the URL property of the FeatureLayer in the XAML?  Three examples below.  The first works but the URL for the Layer is hard wired.  The second or third is what I want to do.  Use the Code Behind to generate either the full String, or just the Layer ID.

<esri:FeatureLayer ID="Counties"
          Visible="False"
          Url="http://www.testlocation.us/ArcGIS/rest/services/Atlas/Atlas/MapServer/22"
          />
                        
<esri:FeatureLayer ID="Counties"
          Visible="False"
          Url="{Binding testID}"
          />

<esri:FeatureLayer ID="Counties"
          Visible="False"
          Url="http://www.testlocation.us/ArcGIS/rest/services/Atlas/Atlas/MapServer/" + {Binding TestID}
          />


Lots of info on the web about Binding, but nothing that seems to help me that I've found.  If we can dial this in, then I think it will be helpfull for may others.

-Tony
0 Kudos
by Anonymous User
Not applicable
It would probably be easier (e.g. less work) to do something like that in code behind. You could determine the feature layer URLs then add them programmatically while the app loads. 
This would allow you to add everything dynamically (or even filter what gets loaded), so if anything was missing you wouldn't throw an exception for a null layer.
0 Kudos
TonyThatcher
Deactivated User
Michael-
I was afraid you were going to say that.
Back to the drawing board for me.  I started looking at that approach and figured that there had to be a way to do it easily via the XAML and Code Behind.  Guess I'm still stuck in my old fasioned, ASP/in line code world.

Will post for the benefit of others when I get this worked out.

-T
0 Kudos
by Anonymous User
Not applicable
Well, if you know for a fact which layers will be added and all that you need to know is the ID, you could write a property that binds to the feature layer URL property, but you will still need to write code to make that happen. For example, something will have to set the property when the app loads.
0 Kudos