Select to view content in your preferred language

Target Sublayer Visibility in Code Behind

1871
13
Jump to solution
07-06-2012 11:23 AM
JaredWhite
Regular Contributor
Hi,
A few weeks ago I discussed how to target sublayer Opacity in code behind with Dominique, the following code is the product of that

                 private void toggleSubLayerOpacity()         {             LayerDrawingOptions layerDrawOptions = new LayerDrawingOptions();             layerDrawOptions.LayerID = 0;             (MyMap.Layers["MyLayer"] as ArcGISDynamicMapServiceLayer).LayerDrawingOptions =                 new LayerDrawingOptionsCollection() { layerDrawOptions };             (MyMap.Layers["MyLayer"] as ArcGISDynamicMapServiceLayer).VisibleLayers = new int[] { 0 };             if (layerDrawOptions.Opacity == 0)             {                 layerDrawOptions.Opacity = 1;             }             else             {                 layerDrawOptions.Opacity = 0;             }         }


This works, however, toggling sublayer visibility would work considerably better for my project versus opacity, as well as increase app performance. How would I go about doing this?
0 Kudos
1 Solution

Accepted Solutions
JoeHershman
MVP Alum
Jared,

The Except() method is meant to return an IEnumerable<T> of all the elements in an IEnumerable<T> that are not a provided IEnumerable<T> (huh :)).  So the usage is like this

   IEnumerable<int> myInts = westTexas.VisibleLayers.Except(new[] {0}); 


Which returns an IEnumerable<int> of all the values in VisibleLayers Except for 0, which is not really what you want. 

The code sample I provided should work to Toggle visibility of a given layer.  You just need to use contains backwards, if .Contains returns false, then pass SetLayerVisibility a value of true

         private void ToggleVisibility(int layerId)         {             var westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;             if ( westTexas == null ) return;               //this will return True if the VsibleLayers includes layerId (is Visible), or False if it is not included (not visible)             bool isVisible = westTexas.VisibleLayers.Contains(layerId);               //This will flip the visbility, if layerId was vsible it rurns it off, if it is not visible it turns it on.             westTexas.SetLayerVisibility(layerId, !isVisible);         } 


Hope that helps
-joe
Thanks,
-Joe

View solution in original post

0 Kudos
13 Replies
JaredWhite
Regular Contributor
here is where I am now in the code, I think I'm close but still need some help on it. The code works to toggle a sublayer off when used, but It won't add the layer back for some reason. Any would be greatly appreciated.

        private void togglecweiSublayer()
        {
            ArcGISDynamicMapServiceLayer westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;
            List<int> visibleLayerList =
                westTexas.VisibleLayers != null
                ? westTexas.VisibleLayers.ToList() : new List<int>();
            if (!visibleLayerList.Contains(0))
            {
                visibleLayerList.Remove(0);
            }
            else
            {
                visibleLayerList.Add(0);
            }
            westTexas.VisibleLayers = visibleLayerList.ToArray(); 
        }
0 Kudos
JoeHershman
MVP Alum
The way to change visibility is to use the SetLayerVisibility method on the ArcGISDynamicMapServiceLayer instead of removing/adding from the VisibleLayers collections, something like.


            var westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;


            bool isVisible = westTexas.VisibleLayers.Contains(0);
            westTexas.SetLayerVisibility(0, !isVisible);



Hope that helps
-Joe
Thanks,
-Joe
0 Kudos
JaredWhite
Regular Contributor
The way to change visibility is to use the SetLayerVisibility method on the ArcGISDynamicMapServiceLayer instead of removing/adding from the VisibleLayers collections, something like.


            var westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;


            bool isVisible = westTexas.VisibleLayers.Contains(0);
            westTexas.SetLayerVisibility(0, !isVisible);



Hope that helps
-Joe


Hi Joe,
Thanks for the response. It seems like this will work, but I'm getting an error saying System.Array does not contain a definition for 'Contains'. How would i fix this?
0 Kudos
JaredWhite
Regular Contributor
Hi Joe,
Thanks for the response. It seems like this will work, but I'm getting an error saying System.Array does not contain a definition for 'Contains'. How would i fix this?


NVM, Just had to add Using System.Linq;
Odd that it didn't automatically suggest that as a solution.

I'm new to using the Enumerable class though, this adds the sublayer just fine, but how would I remove a sublayer from the visible layers list?
If i follow the same implementation method as contains for Except,
e.g.
 
            bool isNotVisible = westTexas.VisibleLayers.Except(0); 


it sends back the exception "'int[]' does not contain a definition for 'Except' and the best extension method overload 'System.Linq.Enumerable.Except<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Collections.Generic.IEnumerable<TSource>)' has some invalid arguments"
0 Kudos
JoeHershman
MVP Alum
Jared,

The Except() method is meant to return an IEnumerable<T> of all the elements in an IEnumerable<T> that are not a provided IEnumerable<T> (huh :)).  So the usage is like this

   IEnumerable<int> myInts = westTexas.VisibleLayers.Except(new[] {0}); 


Which returns an IEnumerable<int> of all the values in VisibleLayers Except for 0, which is not really what you want. 

The code sample I provided should work to Toggle visibility of a given layer.  You just need to use contains backwards, if .Contains returns false, then pass SetLayerVisibility a value of true

         private void ToggleVisibility(int layerId)         {             var westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;             if ( westTexas == null ) return;               //this will return True if the VsibleLayers includes layerId (is Visible), or False if it is not included (not visible)             bool isVisible = westTexas.VisibleLayers.Contains(layerId);               //This will flip the visbility, if layerId was vsible it rurns it off, if it is not visible it turns it on.             westTexas.SetLayerVisibility(layerId, !isVisible);         } 


Hope that helps
-joe
Thanks,
-Joe
0 Kudos
JaredWhite
Regular Contributor
Jared,

The Except() method is meant to return an IEnumerable<T> of all the elements in an IEnumerable<T> that are not a provided IEnumerable<T> (huh :)).  So the usage is like this


  IEnumerable<int> myInts = westTexas.VisibleLayers.Except(new[] {0});



Which returns an IEnumerable<int> of all the values in VisibleLayers Except for 0, which is not really what you want. 

The code sample I provided should work to Toggle visibility of a given layer.  You just need to use contains backwards, if .Contains returns false, then pass SetLayerVisibility a value of true


        private void ToggleVisibility(int layerId)
        {
            var westTexas = TabletMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;
            if ( westTexas == null ) return;


            //this will return True if the VsibleLayers includes layerId (is Visible), or False if it is not included (not visible)
            bool isVisible = westTexas.VisibleLayers.Contains(layerId);


            //This will flip the visbility, if layerId was vsible it rurns it off, if it is not visible it turns it on.
            westTexas.SetLayerVisibility(layerId, !isVisible);
        }



Hope that helps
-joe


Thanks Joe,
I didn't realize this was working because of a strange problem with the my app. The sublayerToggle you provided is being used as an action strung into a button click , but the app also has a Legend with checkboxes controlling the sublayer visibility in my app, when I toggle the layer on or off on the legend first, then the sublayerToggle also works with the button click, but if it hasn't been toggled with the legend, the toggle strung to the button click doesn't do anything. I'm very confused as to why it's doing this, but I'm also pretty sure it has nothing to do with the code you provided me at this point. Thank you very much for the help.
0 Kudos
JaredWhite
Regular Contributor
Thanks Joe,
I didn't realize this was working because of a strange problem with the my app. The sublayerToggle you provided is being used as an action strung into a button click , but the app also has a Legend with checkboxes controlling the sublayer visibility in my app, when I toggle the layer on or off on the legend first, then the sublayerToggle also works with the button click, but if it hasn't been toggled with the legend, the toggle strung to the button click doesn't do anything. I'm very confused as to why it's doing this, but I'm also pretty sure it has nothing to do with the code you provided me at this point. Thank you very much for the help.


Nevermind. I recreated a small silverlight app with the dynamicmaplayer and a button, strung to the ToggleVisibility action, which was uneffective in toggling the visibility. However, when I added a templated legend with checkbox toggle for the sublayers (from http://resources.arcgis.com/en/help/silverlight-api/samples/start.htm#LegendWithTemplates), the button toggle with work after it's been turned on or off with the legend first. Do you know what could be causing this problem?

The Code for the App is
        private void ToggleVisibility(int layerId)
        {
            var westTexas = MyMap.Layers["West Texas"] as ArcGISDynamicMapServiceLayer;
            if (westTexas == null) return;
            bool isVisible = westTexas.VisibleLayers.Contains(layerId);
            westTexas.SetLayerVisibility(layerId, !isVisible);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            ToggleVisibility(0);
        }


And i did get it to throw an exception once. [ATTACH=CONFIG]15869[/ATTACH]
0 Kudos
JaredWhite
Regular Contributor
Solved, using a variation of my original method. For some reason the way it was written required the togglelayer action to be attempted twice before the first time it was successful, the way i have it written now has more control and works out of the gate. It's not as elegant as your code Joe, but it works for me. Thank you for the help!

        private void toggleSubLayerON(int sublayerId)
        {
            ArcGISDynamicMapServiceLayer layer= TabletMap.Layers["Layer"] as ArcGISDynamicMapServiceLayer;
            List<int> visibleLayerList =
                layer.VisibleLayers != null
                ? layer.VisibleLayers.ToList() : new List<int>();
            visibleLayerList.Add(sublayerId);
            layer.VisibleLayers = visibleLayerList.ToArray();
        }

        private void toggleSubLayerOFF(int sublayerID)
        {
            ArcGISDynamicMapServiceLayer layer= TabletMap.Layers["Layer"] as ArcGISDynamicMapServiceLayer;
            List<int> visibleLayerList =
                layer.VisibleLayers != null
                ? layer.VisibleLayers.ToList() : new List<int>();
            visibleLayerList.Remove(sublayerID);
            layer.VisibleLayers = visibleLayerList.ToArray();
        }
0 Kudos
JoeHershman
MVP Alum
I was playing around with this and I notice that after initialization the VisibleLayers collection is still null (which would explain the error).  It is not until a method call has been made to SeLayerVisisibility has been made that this collection is actually available.  This explains the behavior you see because clicking a layer on the Legend will make a call internally to SetLayerVisibility.

I checked this on both 3.0 and 2.4 and see the same behavior.

Personally, I would consider this a bug.  The idea that you cannot check what layers are visible prior to turning one on or off does not make any sense.  I cannot believe this has not been noticed before, but I have not seen a post about it.

I found a work around that seems to work.  Add a LayersInitialized handler and for a SublayerId you know is Visible call SetLayerVisibility(id, false) then SetLayerVisibility(id, true) immediately after that.  This seems to initialize the VisibleLayers collection.

Hope that helps
-Joe
Thanks,
-Joe
0 Kudos