Software Development

Finding things with Virtual Earth

This uses the July 2008 CTP of the Windows Live tools. You can download the Windows Live Tools for Visual Studio.

This is a very introductory post just to show how to find things using the Virtual Earth ASP.NET control.

First you need to add an assembly reference to the Virtual Earth control to your project:

In each page that you want to use the Virtual Earth control you must add a line that looks like this at the top of the file:

<%@ Register Assembly="Microsoft.Live.ServerControls.VE"
    Namespace="Microsoft.Live.ServerControls.VE"
    TagPrefix="ve" %>

This registers the assembly allowing you to use the control.

When you view the ASPX page you will see that you have additional tools in the toolbox that relate to Virtual Earth. The one we are going to look at in this post is the Map control.

From the tool box you can drag a map control onto your design surface. The code it generates will set up a default position and zoom level which centres on the continental United States.

By default the control is a 400x400px square and has been given a name of Map1:

<ve:Map ID="Map1" runat="server" Height="400px" Width="400px" ZoomLevel="4" />

 

To start with we are going to change the defaults to something that is closer to home (well, mine at least) and centre it on central and southern Scotland and zoom in somewhat. I also don’t like the name Map1 so I’m going to change that too:

<ve:Map ID="VEMap" runat="server" Height="600px" Width="400px" ZoomLevel="8"  Center-Latitude="55.75" Center-Longitude="-3.5" />

The first thing I should comment on is the zoom level because it doesn’t really mean anything to anyone. Personally, I’d like to say “here’s a bounding box for the area I want to see, you figure out how to do that and sort out the aspect ratio for me”. Then again, maybe that’s because when I wrote a GIS system for my final year project at university that was what I did. I didn’t constrain the user to specific and artificial zoom levels. The maths behind it isn’t difficult and a modern graphics card can do that with its proverbial eyes closed. Having said that I can understand why it was done that way. It means that none of the maps are generated on the fly, it is all based on pre-existing graphic files that are retrieved as needed. This means no strained servers trying to render maps.

The zoom level ranges from 1 to 19. 1 is zoomed out to the whole world and 19 is zoomed in to street level. In between that it seems to be mostly an matter of experimentation.

As it stands the program will display a map on the page and you can zoom in or out, pan around and change display modes and so on, just like Live Maps.

Next, we’ll add some functionality to find stuff. To that end a text box (SearchTextBox) will be added in order that we can type stuff in, and a button (SearchButton) that we can submit it. The code for the button click event is as follows:

protected void SearchButton_Click(object sender, EventArgs e)
{
    VEMap.Find(string.Empty, SearchTextBox.Text);
}

The two parameters on the Find method match the two text boxes you find on Live Maps. The first parameter is the “what” (i.e. the business name or category” and the second parameter is the “where” (i.e. The address, location or landmark). If you use Live Maps a lot you’ll probably already by used to just ignoring the first box, so I haven’t included anything to populate that parameter and will just leave it empty.

Now, when the application is run the map will update when the button is clicked. It will zoom to the location you’ve specified.

At present there is no mechanism to determine where to move the map to if there is any ambiguity. For example, type “Bolton” and you’ll be taken to Bolton, England rather than Bolton, NY. Type “Washington” and you’ll be taken to the District of Columbia rather than the state. On the other hand type WA (the standard two letter abbreviation for Washington State) and you will be taken to Washington state.

The Virtual Earth control can tell you about all the places that it thought about when it was deciding where to take you. To get that we have to handle the ServerFind event on the map control. In order to do that change the ASPX markup to read:

<ve:Map ID="VEMap" runat="server" OnServerFind="VEMap_ServerFind"  Height="600px" Width="400px" ZoomLevel="8"  Center-Latitude="55.75" Center-Longitude="-3.5" />

And then add a handler in the code behind:

protected void VEMap_ServerFind(object sender, FindEventArgs e)
{
    StringBuilder sb = new StringBuilder();

    foreach (Place place in e.Places)
    {
        sb.Append("<p><strong>");
        sb.Append(place.Name);
        sb.Append("</strong> (");
        sb.Append(place.MatchCode);
        sb.Append(")<br/>");
        sb.AppendFormat("Lat: {0}, Long: {1}", place.LatLong.Latitude, place.LatLong.Longitude);
        sb.Append("</p>");
    }
    ResultLiteral.Text = sb.ToString();
}

Note: A Literal control called ResultLiteral has also been added to the page to display the results.

The ServerFind event will be raised by the map control when it finds stuff, however, you’ll notice that the page does not include the text we’ve built up. You might be thinking at this point that the event isn’t being raised at all, but put a break point down inside the code of the event. You’ll see the breakpoint is being hit.

The problem is that the ServerEvent is being handled as part of an AJAX postback rather than a page postback. If you look at the stack trace you’ll see that the map control has its own internal UpdatePanel that you would normally need to indicate that part of the page was AJAXified, so to speak. So to ensure that the code works as we would expect it to we need to add some things to the ASPX file.

First off we need a ScriptManager:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
</asp:ScriptManager>

And secondly we need an update panel of our own in order to put the controls that will be updated when the ServerFind event is handled. So the update panel, with the controls we created earlier, looks something like this.

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
    <p>
        Search:
        <asp:TextBox ID="SearchTextBox" runat="server" />
        <asp:Button ID="SearchButton" runat="server" Text="Search"
          onclick="SearchButton_Click" />
    </p>
    <p>
        <asp:Literal ID="ResultLiteral" runat="server" />
    </p>
    </ContentTemplate>
</asp:UpdatePanel>

If we search for Bolton again the results look like this:

As you can see there are several Boltons in the world.

The FindEventArgs contains many bits of information, but in the sample above we’ve just concentrated on the Place. This gives you details of the places that have been found, how good a match it thinks the place is and where the place actually is. Obviously, the more specific you are in the search the more accurate the results are going to be and the more chance you have of getting an exact match.

Note: At present there is not much documentation for the Virtual Earth ASP.NET control. Much of the functionality has been gleaned from reading the documentation for the “classic” Virtual Earth control which is customisable through Javascript. I also found a bug, which has been reported to Microsoft, that if you happen to be in Birds Eye view then the find functionality does not work.

5 thoughts on “Finding things with Virtual Earth

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s