Master/Detail with ASP.NET AJAX and the MS Virtual Earth Control

I was recently working on a research project with the purpose of exploring how ASP.NET AJAX could be combined with Microsoft's Virtual Earth Map Control to implement the common master - details UI pattern.  Our application allows users to browse zip-codes using the Virtual Earth Map Control and we thought it would be useful to display details for the zip-code as it was being hovered over.

While investigating this I created a prototype web application that does the following:

  1. Renders purple polygons on the VEMap surface representing the following 3 zip-codes: 32224, 32246, and 32256.
  2. When the user hovers over the polygons, 2 things happen:
    1. The border of the polygon changes to a thicker width.  This is a visual cue meant to inform the user of their action
    2. The information displayed in the table to the right of the map updates.  This table displays some high-level demographic and weather statistics.

Live Demo | Download

Here is a brief explanation of how I accomplished this.  The example uses PageMethods to fetch the latitude and longitudes for the zip-codes.  If you are not familiar with PageMethods you should Google it to find out more, or read about it here.

Load the Map

First I added a HTML div element to the page that will contain the map. 

<div id="myMap" class="map" />

Following closely to the MSDN documentation, I named the div myMap and provided a css class for controlling height and width.  Next I added a javascript function for handling the ASP.NET AJAX pageLoad client side event.  There are 2 points here to be aware of:

  1. You don't have to explicitly subscribe to the client side pageLoad function.  Just like the server side AutoEventWireup, as long as you add a function named pageLoad to the page, the ASP.NET AJAX framework will find it
  2. pageLoad is invoked on both full and partial postbacks.  So if you need to conditionally execute logic based on the type of postback you can use the isPartialLoad property of the event args object.

With this in mind, here is the javascript pageLoad function.  You will notice 2 other items here as well.  The first is that we are also using the AttachEvent method on the VEMap to handle the onmouseover and onmouseout events.  The second is that we are using the PageMethods proxy to invoke the GetZipCodes page method.  We will look at these items next.

function pageLoad(sender, args){
    if(!args.get_isPartialLoad()){
        //  create the map
        map = new VEMap('myMap');    
        //  set the dashboard size to tiny so it doesn't get in the way
        map.SetDashboardSize(VEDashboardSize.Tiny); 
        //  load the map
        map.LoadMap(); 
        
        //  attach to the events we care about
        map.AttachEvent("onmouseover", onMouseOver);   
        map.AttachEvent("onmouseout", onMouseOut);   
        
        //  add the customers to the map
        PageMethods.GetZipCodes(plotZipCodes);
    }
}

Handle the Map Events to Provide Visual Cues

Next, we will implement the onmouseove and onmouseout event handlers so we can give the user a nice visual cue of their action.  The argument passed the the event handlers can be used to lookup the VEShape object that fired the event.  In the onmouseover handler we will use this to find the currently selected shape and increase its border width.  In the onmouseout handler we will revert it back to its original value.  Here are the handlers that do this ...

function onMouseOver(e){
    if(e.elementID){
        //  fetch the polgon we are moused over
        var polygon = map.GetShapeByID(e.elementID);
        //  increase its width
        polygon.SetLineWidth(2); 
    }
}

function onMouseOut(e){
    if(e.elementID){
        //  fetch the polgon we are moused over
        var polygon = map.GetShapeByID(e.elementID);
        // restore its width
        polygon.SetLineWidth(1); 
    }
}    

Plot the Zip-Codes

Now we are ready to add the code that handles adding the VEShape's to the VEMap.  As shown earlier, the pageLoad method invokes the GetZipCodes page method.  This is done asynchronously and when execution completes the plotZipCodes javascript function is invoked.  This handler is responsible for parsing the resulting data stream and picking out the latitude/longitude pairs that make up each of the three zip-codes.  Once the latitude and longitude pairs are extracted, a new VEShape object is added to the map.  The majority of the code in this function handles the parsing.  After the latitude and longitudes are extracted, a VEPolygon is created from the coordinates and added to the VEMap.    

function plotZipCodes(result){

    if(result && result.length > 0){
        //  split the zipCodes
        var zipCodes = result.split('END');
        //  keep track of all of the latlongs
        //  so we can make sure to set the zoom
        //  correctly
        var veLatLongs = new Array();            
        
        //  parse out the lat/longs for each of the zip-codes
        for(index = 0; index < zipCodes.length; index++){
        
            var zipCodeSegments = zipCodes[index].split('|');
            
            var zipCode;
            var zipCodeBounds = new Array(zipCodeSegments.length - 1);
            for(var i = 0; i < zipCodeSegments.length; i++){
            
                if(i == 0){
                    //  this is the zipcode id
                    zipCode = zipCodeSegments[i];
                }
                else{
                    //  this is a latlon pair
                    var lat = zipCodeSegments[i].split(',')[0];
                    var lon = zipCodeSegments[i].split(',')[1];
                 
                    zipCodeBounds[i - 1] = new VELatLong(lat, lon);                               
                }
            }
            
            //  create the polygon
            var polygon = new VEShape(VEShapeType.Polygon, zipCodeBounds);                    
                            
            //  set the colors
            polygon.SetFillColor(new VEColor(0,0,255,.2));
            polygon.SetLineColor(new VEColor(0,0,255,1));
            polygon.SetTitle(zipCode);
            polygon.SetLineWidth(1); 
            
            //  don't display the shapes icon
            polygon.HideIcon();      
            
            //  add our new polygon
            map.AddShape(polygon);   
            
            //  keep track of all of the bounds so we can 
            //  set the view correctly
            veLatLongs = veLatLongs.concat(zipCodeBounds);
        } 
        
        //  set the view to these points
        map.SetMapView(veLatLongs);                                     
    }
}

Display Zip-Code Details

Finally, the last step.  As mentioned earlier I want to display demographic details for the zip-code the user is currently selected.  I am doing this by adding a DetailsView to the page embedded in an UpdatePanel.  I have setup an AsyncPostBackTrigger for the UpdatePanel.  This trigger is an asp:Button with its style set to hidden so it is not displayed on the screen - I will use this as a hook to cause the UpdatePanel to refresh when the use mousesover a polygon by forcing a postback using the buttons id.  To do this I need to update the onMouseOver handler as follows ...

function onMouseOver(e){
    if(e.elementID){
        //  fetch the polgon we are moused over
        var polygon = map.GetShapeByID(e.elementID);
        //  increase its width
        polygon.SetLineWidth(2); 
        
        //  get the value from the title
        $get('<%= this.hdnZipCode.ClientID %>').value = polygon.GetTitle();
        // get the id of the element
        // force the update panel to update
        __doPostBack('<%= this.btnUpdateZipCode.ClientID %>', '');                
    }
}

That's it. Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/57

Listed below are links to weblogs that reference Master/Detail with ASP.NET AJAX and the MS Virtual Earth Control:

» Master/Detail with ASP.NET AJAX and the MS Virtual Earth Control from Techniques
This post details how ASP.NET AJAX could be combined with Microsoft's Virtual Earth Map Control to implement [Read More]

Comments


Posted by: geoff on August 21, 2007 10:30 PM

Hey Matt,
Great blog...Quick question have you had any luck getting vs2008 jscript intellesense to work with the virtual earth?

Great post! I just looked at some of your other posts and I think I going to have to subscribe to your feed.

On a related note to this post, You might be interested that there is an all new ASP.NET AJAX Virtual Earth Mapping Server Control that abstracts out all the JavaScript necessary when implementing Virtual Earth. This control is really cool! You can find it at: http://simplovation.com/Page/WebMapsVE.aspx

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Sponsor

Recent Comments

  • Chris Pietschmann wrote: Great post! I just looked at some of your other posts and I think I going to have to subscribe to yo...
  • geoff wrote: Hey Matt, Great blog...Quick question have you had any luck getting vs2008 jscript intellesense t...

Sponsor