ThinkGeo.com    |     Documentation    |     Premium Support

Generic Exception Handling with Tile Providers (GMaps, Bing, OSM..)

 Hi,


I would have a question regarding the usage of external Tile Providers (Google Maps and so on): How can I ensure a generic exception handling, "provider-agnostic"? One uses the specialized classes such as GoogleMapsLayer, "BingLayer" and so on as base classes, sets the DrawExceptionMode to DrawException and overrides DrawExceptionCore in the subclass (as I have learned by reading some forum threads here).


This approach would work for a given provider, yet I cannot wrap my head around a generic solution, seeing that the base class for all the specialized layers is, of course, Layer. This class doesn't expose the precious DrawExceptionCore method, moreover one must implement DrawCore whose base method is, of course, abstract. 


I have also tried to embed the exception handling within the parent LayerOverlay, to no avail. Drawing the exception only renders the "infamous" :) pink background with the cross in the center. What is more, all the threads return with the exit code "0" which should indicate a smooth/problemless run, which really shouldn't be the case when the tile provider's server couldn't be reached. Moreover, If I choose to let the exception be thrown I cannot find the spot in which I am supposed to catch it.


Is there a generic solution available?


My specific use case would be the handling of connectivity exceptions (e.g. no Internet connection, therefore one cannot use external Tile Providers). As mentioned, this would run great if I were to limit myself to a single class such as GoogleMapsLayer, override the DrawExceptionCore and handle the exception there. Would be very interested to see if another solution is available, seeing that a switch to OSM is in the books. Repeating the generic exception handling in each subclass is of course pointless.


Thank you in advance for your support! I am able to provide any other details per request.


P.S. : I'm using ThinkGeo WPF Edition 4.5 running .NET (C#).



 Hello Cosmin,


 
Thanks for your post, about the WPF multithread exception, we have updated the DrawingExceptionMode in our newest version, now you can use 
InMemoryPointsFeatureLayer.DrawingExceptionMode = DrawingExceptionMode.DrawException

 
Could you please update to the 5.5 and have a try?
 
Regards,
 
Gary

Cosmin, 
  
   I’m not sure what Gary was talking about above, maybe it’s related to a ticket I don’t know about.  Speaking directly to your question I can see what you are trying to do and the issues you are running into.  I can think of a few ways to handle this and let me get your feedback. 
  
 1. Create a wrapper layer that inheritys from Layer and has a collection on layers on it.  Override the DrawCore, Open, and Close methods and in them loop through the collection and call the underlying methods on the items.  In this way you can set each layer to throw exception and then catch it in this wrapper and do whatever you would like in the DrawException method.  Of course this means you need to wrap something and create a new layer. 
  
 2. This is a variation of the first method except that you just wrap one layer at a time.  This gives you control over each layer separately. 
  
 3. We add a set of events to straddle the DrawExceptionModeCore method.  In this case you can attach methods to the events of each layer you want and do your drawing in an even rather then through overriding the method.  This, I think, is the best way to go and is a common way to deal with protected overridable methods.  In most places where we have a “Core” method we also have a set of events to go with them. 
  
 4. We look at the drawing exception system in the TileOverlay in the WPF Edition, in this way you could deal with the errors tile by tile in the overlay.  I would imagine this would be handled through a set of events as well. 
  
 We are open to any suggestions as well. 
  
 David

Hey guys, 



Thanks for the reply! I'm afraid David was more on the money this time, Gary :)  

So David, I'm going to try and handle it with the 3rd method as you said, it looks the cleanest.  



I've quickly looked through the events exposed by LayerOverlay as well as GoogleMapsLayer for instance and I can't find any suitable, thoughts on that please? There's only Drawn, DrawTileProgressChanged, a small code snippet would be marvelous! 



The wrapper class could also work as well. My quick suggestion would be to add a small niche between the normal Layer and the "BackgroundLayer s", that do the external tile providing, don't know if that makes so much sense, architecture-wise. 



I'll look into this feature again in January, for the time being we're looking beforehand if an internet connection is available before adding the Background Map Layer.  



Thank you for your support!



Cosmin, 
  
   We are adding the events right now.  The events on the layer will be DrawingException and DrawnException.  The two events will pass you a GeoCanvas and an exception object. The DrawingException will also have a cancel argument to suppress the default drawing that happens in the protected virtual DrawExceptionCore method.  I will let you know when it will be available and the version to get. 
  
 David 
  


YUHUUUUUU!!! 
  
  Thanks a lot!!! It will also solve some of my problems.

Carlos, 
  
   Check out the developer build 5.5.33.0. :-) 
  
 David

Cosmin & Carlos,



  We made one small change to the event arguments.  We changed the property of GeoCanvas to Canvas to be more consistent with other places we we use the Canvas.  There is no functional change just naming.


Here is a little sample code of it in action as well. :-)



            //Hook up the event to all of the layers in the overlay
            foreach (Layer layer in layerOverlay.Layers)
            {
                layer.DrawingException += new EventHandler<DrawingExceptionLayerEventArgs>(layer_DrawingException);
            }

        //Draw and image to the tile.  You could do anythign with the cavnas though such as
        // draw the exception name etc.
        void layer_DrawingException(object sender, DrawingExceptionLayerEventArgs e)
        {
            e.Canvas.Clear(new GeoSolidBrush(GeoColor.FromArgb(128, 255, 192, 203)));
            Bitmap tempImage = new Bitmap(@"C:\Somewhere\ErrorImage.png");
            MemoryStream stream = new MemoryStream();
            tempImage.Save(stream, ImageFormat.Png);
            stream.Seek(0, SeekOrigin.Begin);
            tempImage.Dispose();
            e.Canvas.DrawScreenImageWithoutScaling(new GeoImage(stream), e.Canvas.Width / 2, e.Canvas.Height / 2, DrawingLevel.LabelLevel, 0, 0, 0);
            e.Cancel = true;
        }

 




David