ThinkGeo.com    |     Documentation    |     Premium Support

Unloading Overlays

I'm making a WPF application using Desktop Edition 3.0.  I've set it up so that a user can select from a set of shape files to display.  I'd like to also allow the user to change the layers (shape files) displayed, but I don't see any way to "unload" an overlay once I've loaded it.



I found what I was looking for: 
  
 WpfMap1.Overlays.Clear;

Steve,



  I'm glad you found that.  I have some more information to share with you though.  If you added the overlay using the constructor that takes a string key you can also remove them using the Map.Overlays.Remove(string key) as well if you want to remove just one by the key.  You have to use the same key you used to add them like Map.Overlays.Add(string key, overlay).  One thing to keep in mind is if these overlays contained layers which may be shape file types like using the LayerOverlay where you added ShapeFileFeatureLayer I suggest you close all of the layers before you remove it if you no longer need them.  You can do a loop through Overlay.Layers and call the Layer.Close on it.  This is to clean up anything right away.  Of course during garbage collection if the reference is orphaned it will clean it up but I like to advocate being pro-active with file resources.  I whipped up some code to show you this.  You can call the UnloadOverlay with a key to unload one or with just the collection over overlays to unload them all.  It will look at each overlay and if it is a LayerOverlay then it will close all of the layers before it removes them.




        private void UnloadOverlay(string key, GeoCollection<Overlay> overlays)
        {
            CloseLayersInOverlays(new Overlay[] { overlays[key] });
            overlays.Remove(key);
        }

        private void UnloadOverlay(GeoCollection<Overlay> overlays)
        {
            CloseLayersInOverlays(overlays);
            overlays.Clear();            
        }

        private void CloseLayersInOverlays(IEnumerable<Overlay> overlays)
        {
            foreach (Overlay overlay in overlays)
            {
                if (overlay is LayerOverlay)
                {
                    LayerOverlay layerOverlay = (LayerOverlay)overlay;
                    foreach (Layer layer in layerOverlay.Layers)
                    {
                        layer.Close();
                    }
                }
            }
        }
 




David



Thank you very much.  It would have taken me some time to see this. 
  
 Still a question though; I’ve been keeping layers closed when not necessary.  (The only time that I’ve needed to have a layer open is to “GetBoundingBox”.)  Will “UnloadOverlay” do anything in this situation?  Alternately, is there any need to keep an overlay open? 
  
 Perhaps this is a separate thread, but you can probably answer it quickly.  I’m using ArcGIS files that have styles specified in xml files.  Is there any way to load the shape file and have it read the ESRI styles?

Steve, 
  
   No problem, I like to provide little pieces of sample code.  One they are easy to build and they are so much better then typing the explanation in paragraph form.  I guess some code is worth a thousand words in this case.   
  
   We will open the layer when they go to draw and we leave them open afterward.  We do this to get some speed because many people pan or zoom in and while opening the layers doesn’t take that much time it still takes some time and if you have hundreds of them you would feel it.  We have the layers coded in such a way if you open an already opened layer or close an already closed layer then it just ignores the call and doesn’t raise an exception so that is good.  If you are removing the overlay just to not let it draw but you may add it again I suggest you mark the IsVisible property false on it and leave it open and in place, this will save some time and coding.  If you close them and then draw with it then we will have them open.  If your application is just hte map then closing them when you clear them doesn’t buy you much but if you application is many more screens then it is good to close and cleanup everything when you are done with it.  I am just a pessimistic programmer and like things closed when not using them.  It cuts down on the ‘wierd’ things that can happen when you leave things open for long periods of time and forget about them.  Since the garbage collector is not deterministic as to when it will clean up when a class offers a close or dispose I tent to use it. 
  
 As to the XML files we do not have anything that can read them off the shelf.  I will add this to the new features list but no guarantee if or when it will make it in.  If having this will save you allot of time I would suggest you build it.  Reading the XMl might not be too tough and really you just need to identify all of their styles and map them over to ours.  If you don’t have the time or expertise then you can always explore our profession services teams.  The guys are really good and they can get a quote to you.  You can contact your sales rep on this and he can help you get the ball rolling.  This is of course if you think it will save you time and money in the end. 
  
 David

Thank you, this is very helpful. 
  
 This is a major project that will expand significanly if I am successful.  It is very likely that we will ask for help at some point in the future.  I don’t know enough right now, however, to ask for help in an efficient way.  Another apect is that I’m using Prism (Object Pascal) for WPF in Visual Studio.  Do you have any people using Prism? 
  
 After reading your response above, I realized that I really don’t need to clear overlays, the IsVisual property is what I want.  However, it seems like layers that have been buffered don’t clear when I change the IsVisible proberty.  Is there a way to clear the buffers for an overlay?

Steve, 
  
   I don’t know of any people using Prism but we have allot of customers and many of them I never get to work with.  One thing I would suggest and not to push consulting at all but I really find it useful.  Schedule some consulting time maybe about 8-10 hours and go over you application with us and all the requirements you have.  We can then review them and point you to all the APIs and correct techniques to build your scenario.  We have had a number of people come on site and do this and they found it very rewarding.  Of course we can help in the forums but it is not as effective as we are setup more to deal with single issues. 
  
   On the overlay issue with buffering I have a few questions.  Do you have the latest public release as of Monday?  When you set the IsVisible did you call a Refresh and pass in that Overlay?  I checked the code and it shouldn’t draw the cache if you refreshed and the IsVisible is false.  If you still have issues can you send me a very small sample application with just a map, a few points or small shapefile showing the issue? 
  
 David

I strongly endorse the suggestion of contracting for a little bit of ThinkGeo consulting time.    It has really optimized our development efforts to get that initial starting boost when in the "which of 45 ways…" stage.

Ted, 
  
   Thanks for the endorsement!  I have seen it make a big difference on various projects where we help scope it out from the beginning and it really doesn’t take all that much time, depending on the application of course. 
  
 David

I’ve loaded DesktopEditionFull3.0.415.  I think that it is the most recent. 
  
 What do you mean by “call a Rfresh and Pass in that Overlay” ? 
  
 Here is the code that I’m using: 
  
   For i := 0 To Layers.Count - 1 Do 
     With lyr := Layers.Layer, ovl := Layers.Overlay Do 
       If InteraControlsPrism.CheckItem(sFiles.cilShapeFiles.Items).IsChecked Then 
         ovl.IsVisible := True Else ovl.IsVisible := False; 
   Map.Refresh(); 
  
 Layers is a List of objects that have a ShapeFileFeatureLayer field (as well as other fields).

Hi Steve,


There is an overload of the Refresh method that you can pass in an overlay. This overload will clear all the caches on the passed in overlay and redraw it. So you’d better call this overload when you change the IsVisible property. And the code is like this:



Map.Refresh(overlay);


 
Any more questions please let me know.
 
Thanks,
 
sun

So, I have code sprinkled all over the place to overlay.Lock.EnterWriteLock, update layers, overlay.Lock.ExitWriteLock… and then map.Refresh.   Is this code still going to work.   From the miriad of RC2 posts, it appears that this will refress ALL overlays, rather than just the one I have modified?   Do I really need to change this code to pass in the explicit overlay that I just locked and unlocked? 
  
 Do I still need the locks if in single threading mode?  If in multi-threading mode? 
  
 I know this new model is simpler for new developers and I applaud that.   But an all encompassing post for the implications of the new model for "legacy" code would be very much appreciated. 
  


Hi Ted, 
  
 The lock system you mentioned can still work in the RC2, and this will just refresh the locked overlays like before but not all the overlays.  
  
 You don’t have to switch your locked code to the refresh overload because they almost do the same work in the single threading mode.   
  
 In the RC2 you don’t need the locks ever in the single threading mode but you still need it if you want to use multi threading. 
  
 Any more questions please let me know. 
  
 Thanks, 
  
 sun 


I'm not sure that I have the proper version installed (I've installed three, as they have been updated). I get the error message that there is no overlaod method with one arguement.  Did earlier versions not have the overload?



Steve, 
  
   You are correct, we added this to give more control of what was refreshed.  The reasoning is in the past you had to set the Overlay.Lock.IsDirty == true  before calling the Map.Refresh() method.  This was because we expected the average user to be in multi threaded mode and in that case exiting the write lock would set that dirty flag for you.  In single thread mode you had to set the dirty flag yourself.  When we made the switch back to single threaded mode being the way we expected the average developer to use the system we thought the IsDirty on the Overlay.Lock was a bit excessive and thought and overload on the Refresh would be a much more natural place.  Now if you call just Refresh() then in single threaded mode it clears all of the caches.  You can also use the overloads to refresh a single layer and also a IEnumerable<Overlay> number of Overlays.  Sorry it is a bit confusing because of the history but new developers comming from now it will be much better in single threaded mode and with the overloads on the Refresh. 
  
 David

Steve, 
  
   Also you need build 415 or higher.  If you got the latest version try cleaning your solution as sometimes the old dlls stick around a bit.  Make sure after you re-compile that you check you bin folder to make sure the right dll is getting sucked in. 
  
 David

Yes!  It all works great now.  Thank you. 
  
 Also, it helps to understand the history.  I will be using Map Suite in a multi-threaded application.

Steve, 
  
   Glad things are working!  It is always good to mention the threading mode in the future.  I can’t always keep my customers straight. :-) 
  
 David