Continuously Display Lat Lon Coordinates in a Bing Maps Silverlight App

by James Richards April 12, 2010

Overview

This article presents code and a brief tutorial showing how to continuously display the real world latitude / longitude coordinates of the mouse location in a Bing Maps Silverlight Application.

You can view a live sample or download the source code.

Tutorial

Create a new Bing Maps Silverlight application called LatLonApp using the steps shown in my previous Getting Started with the Bing Maps Silverlight control post.

Open the solution in Blend 3, and open the MainPage.xaml user control.

Select the Map control in the Objects and Timeline Window

image

In the upper right hand corner, enter the name “MyMap” for the Name property in the Properties window and hit return.

image

Select the TextBlock tool in the toolbar, and click and drag on the artboard to add new text block to the project.

image

Position the text block in the lower right, just above the scale bar. Change the name the text block to “Coords”.

In the Properties window, set the Text property to “Lat, Lon” and the justification to Right.

image

image

Ensure that the Horizontal Alignment is set to Right, the Vertical Alignment is set to Bottom, the Left and Top Margins are set to 0 and the Right and Bottom margins are set to 5 and 57 respectively.

image

Notice how the text on the scale bar has a 1 pixel white drop shadow. Next, we’ll duplicate that effect for the Coords text block.

Click on the Assets tab in the upper left, and then select the Effects category. This will display any effects you have registered with Blend on the right hand side of the split window.

image

Drag the DropShadowEffect onto the Coords text block.

image

This will add the effect to the text block, select the effect in the Objects and Timeline window, and display the effect’s properties in the Properties window on the right.

Change the Blur Radius to 1, the Color to White, and the Shadow Depth to 1.

image

Now the text block is styled in the same way as the scale bar text.

image

Select the Map in the Objects and Timeline window or on the artboard and click the Events icon in the upper right hand corner of the Properties window.

image

Find the MouseMove event, enter MyMap_MouseMove and hit enter.

image

This will create a new event handler and open up the code behind file MainPage.xaml.cs.

image

At this point you can either code up the event in Blend, or switch back to Visual Studio. I prefer to switch back to Visual Studio for the Intellisense. Note that you could also have switch back earlier and created the event in Visual Studio as well.

Make sure that all of the files are saved before switching back by choosing Save All from the File menu or pressing Ctrl+Shift+S.

When you switch back to Visual Studio it will notice that the files have been modified and present a dialog asking if you want to reload the file(s). Click Yes to All.

image

Open the MainPage.xaml.cs and add a using statement for the Microsoft.Maps.MapControl namespace.

Add the following code to the MyMap_MouseMove event.

private void MyMap_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
    Point viewportPoint = e.GetPosition(MyMap);
    Location location;
    if (MyMap.TryViewportPointToLocation(viewportPoint, out location))
    {
        Coords.Text = String.Format("Lat: {0:f4}, Lon: {1:f4}",
            location.Latitude, location.Longitude);
    }
}

This code gets the current mouse position in Viewport coordinates and transforms the Point to a latitude longitude Location. If the transformation is successful, the latitude and longitude are rounded to 4 decimal places and the Coords text block is update to display the coordinate.

Press F5 to compile and run the project. As you move the mouse around the map, the coordinates are displayed above the scale bar.

image

Wrapup

In this article you learned how to continuously display the real world latitude / longitude coordinates of the mouse location in a Bing Maps Silverlight Application.

You can view a live sample of the application or download the source code.

Additional Resources

Tags: , , ,

Bing Maps | Silverlight

Getting Started with the Bing Maps Silverlight Control, Visual Studio 2008 and Blend 3

by James Richards April 08, 2010

Overview

This walkthrough shows how to create a new Bing Maps Silverlight Control project with either Visual Studio 2008 SP1 or Blend 3. While some of this material has been covered on other sites and blogs, I’m writing about it here for two reasons:

  1. Some of the other posts are now outdated, using older, beta or CTP versions of the APIs and development tools.
  2. In future posts about developing with the Bing Maps Silverlight Control, I want to be able to refer to this “Getting Started” guide so I don’t have to keep repeating the basics.

Download and Install the Development Tools

If you haven’t already done so, download and install the following applications, SDKs and Toolkits:

Required

VS2008

Microsoft Visual Studio 2008 SP1 (Includes .NET Framework 3.5 SP1)

Silverlight Microsoft Silverlight 3 Tools for Visual Studio 2008 SP1

Blend

Expression Blend 3 or Expression Studio 3
Bing Bing Maps Silverlight Control SDK v 1.0.1

Optional

SilverlightToolkit Microsoft Silverlight 3 Toolkit November 2009

 

 

[more]

Setup a Big Maps Developer Account Using Your Windows Live ID

image

If you don’t already have a Windows Live ID, you’ll need to signup for one on the Windows Live site: https://signup.live.com/signup.aspx

One you have your Windows Live ID, go the the Bing Maps Developer Portal: https://www.bingmapsportal.com/

Click on the “Create or view Bing Maps keys” link in the left menu:

image

When prompted, login with your Windows Live ID. After logging in, you will be redirected to the proper page.

Enter the Application Name and the URL, and click the Create Key button.

image

Here you can see I’ve created two keys. One for development and testing through the http://localhost url and one for running applications on a live URL (in this case, my blog.) I’ve blacked out the actual keys.

Create a New Bing Maps Silverlight Application with Visual Studio

When creating a new Silverlight application, you can start with either Visual Studio or Blend. First we’ll look at how to create the application with Visual Studio. Then in the next section we’ll see how it’s done with Blend.

Start Visual Studio 2008 and choose File > New > Project…

Select Silverlight from the Project types tree, and Silverlight Application from the Templates list.

Give your application a name and click OK.

image

A dialog will appear asking if you want to host the application in a new web site. Make sure this option is checked, select ASP.NET Web Application Project, and click OK.

image

After the project is created, add references to the Bing Maps assemblies.

Right click on the References folder in the BingMapsApp project and choose Add Reference…

image

Select the Browse tab and browse to the Libraries directory in the Bing Maps Silverlight Control installation folder. The default installation location is C:\Program Files\Bing Maps Silverlight Control\V1\Libraries.

Select both the Microsoft.Maps.MapControl.dll and Microsoft.Maps.MapControl.Common.dll assemblies, and click OK.

image

image

Modify the xaml for the MainPage.xaml user control by adding an xml namespace declaration for the Bing Maps assembly.

image

xmlns:bing="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"

Note: The samples on Microsoft’s Bing Maps Silverlight Control Interactive SDK all use the “m” prefix for the namespace, but I prefer to use “bing” as it makes the code a little more expressive. Hat tip to Bobby Diaz’s Bing Maps Silverlight MVVM Sample for that idea.

Add a <bing:Map …/> element inside the layout root and set the CredentialsProvider property to the key that you generated earlier.

image

At this point, you should be able to press F5 and see the default map in your browser.

image

If you see the “Invalid Credentials” message then double check to make sure you have properly set the CredentialsProvider property.

image

At this point I like to clean up the Web project a little bit.

Open up the BingMapsAppTestPage.aspx page, select everything from <!DOCTYPE … down to the bottom of the file, and Ctrl+C to copy it to the clipboard.

Open up the Default.aspx page, delete everything from <!DOCTYPE … down to the bottom of the file, and paste in the contents from the clipboard.

Save the Default.aspx file.

Delete the BingMapsAppTestPage.aspx page and the BingMapsAppTestPage.html file.

Right click on Default.aspx and choose Set As Start Page…

image

Press F5 to run the project and confirm that the control is now hosted in the default page.

 

 

Create a New Bing Maps Silverlight Application with Blend

Now that we’ve covered how to create a new Bing Maps Silverlight application with Visual Studio 2008, lets take a look at how to accomplish the same task with Blend 3.

Start Blend 3 and choose File > New Project…

Select Silverlight from the Project types tree, and Silverlight 3 Application + Website from the template list.

Give your application a name, and click OK.

image

When you create a new Silverlight project in Blend, the structure of the web site is different than if you had created it in Visual Studio. The Silverlight app is hosted in an html page rather than an ASP.NET aspx page.

image

After the project is created, add references to the Bing Maps assemblies.

Right click on the References folder in the BingMapsApp project and choose Add Reference…

image

Browse to the Libraries directory in the Bing Maps Silverlight Control installation folder. The default installation location is C:\Program Files\Bing Maps Silverlight Control\V1\Libraries.

Select both the Microsoft.Maps.MapControl.dll and Microsoft.Maps.MapControl.Common.dll assemblies, and click OK.

image

image

Click the Asset Library button and type “map” in the search box to filter the assets to those controls that contain the phrase “map” in their name. Then select the Bing Maps Silverlight Control from the available choices.

image

Note: The preceding screen shot shows two controls named “Map”. The other one is ESRI’s ArcGIS API for Microsoft Silverlight/WPF Map Control. If you also happen to have this library installed, make sure you choose the correct Map.

After selecting the Map control, it will appear below the Asset Library button.

image

Double click the Map control button to add a map to the artboard at the default size.

image

Click on the Xaml button on the upper right hand side of the artboard to switch to Xaml view.

image

Notice that when you added the Map control Blend automatically added a namespace declaration for you.

image

Since the automatically generated namespace name is rather verbose, change it to “bing”.

image

Click the Design button on the upper right hand side of the code window to switch back to the Design view.

In the Properties window Layout bucket, the right and bottom margins will have defaulted to 240 and 180 respectively.

image

Set each of these properties to 0 so that the map fills the whole layout.

image

image

At the bottom of the Properties window, click arrow next to the Miscellaneous tab to expand it.

Paste your API Key into the text box for the CredentialsProvider property and hit return.

image

At this point you can click F5 to compile and run the project. Notice that the map does not fill the entire browser window like it did with the Visual Studio solution we built in in part 1.

image

This is because Blend sets an explicit Width and Height by default when creating a User Control as part of a new project, while Visual Studio sets DesignWidth and DesignHeight properties with the “Ignorable” namespace prefix.

Switch back to Xaml view, and replace the names of the Width and Height properties with d:DesignWidth and d:DesignHeight.

image

Now run the project again and the Map will fill the whole browser window.

As was the case in the Visual Studio walkthrough, if you see the “Invalid Credentials” message then double check to make sure you have properly set the CredentialsProvider property.

Wrapup

This post presented two methods for creating a new Bing Maps Silverlight Control project. The first method gave a walkthrough using Visual Studio 2008 SP1, and the second showed how to accomplish the same task with Blend 3. You can use either method, depending on which tool you are most comfortable with.

Additional Resources

Microsoft

Bing Maps MVVM Samples

Tags: , , ,

Bing Maps | Silverlight

Implementing Model-View-ViewModel with the Bing Maps (Virtual Earth) Silverlight Map Control

by James Richards September 28, 2009

Overview

I’ve been looking at the Bing Maps (Virtual Earth) Silverlight Map Control and thinking about how to use it in a Silverlight application that implements the Model-View-ViewModel pattern. If you’re not familiar with this pattern, check out Shawn Wildermuth’s MSDN Article Model-View-ViewModel in Silverlight 2 Apps.

I’ve created a simple proof of concept application that implements the pattern with two Views: a Map based View and a Data Grid based View. The application displays a map of well known surf spots in the Los Angeles area, along with some basic information about each spot in an accompanying data grid.

image

[more]

There is no live example posted for this one, as Microsoft has not yet released the Silverlight Map Control with a “Go Live” license. But you can download source code from here to try it out on your own system.

Synchronizing Multiple Views with the ViewModel

Both Views work off the same ViewModel and stay synchronized via events that the ViewModel fires back to the Views after user gestures.

image

There are two main types of user gestures where this comes into play:

  1. When the map is first loaded or the user pan/zooms the map, the ViewModel is notified of the new map extent. The ViewModel then loads surf spots that fall within the new Map Extent from a Repository. An event is fired back to both Views and they update themselves to display only the surf spots that were loaded based on the new map extent.
  2. When a user clicks on a surf spot in either the map or the list, the ViewModel is notified of the newly selected surf spot. An event is fired back to both views and they update themselves to display the selected spot. 

In the next section, I’ll take a closer look at the first example.

Loading Surf Spots from the Repository

The xaml file for the SurfSpotsMapView markup contains just a Map with a specified ViewChangeStart event.

SurfSpotsMapView.xaml

<UserControl x:Class="Map.Client.Views.SurfSpotsMapView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    mc:Ignorable="d"
    d:DesignWidth="500"
    d:DesignHeight="500">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="Map1" ViewChangeStart="Map_ViewChangeStart">          
        </m:Map>
    </Grid>
</UserControl>

The ViewChangeStart event fires whenever the map extent is about to change. This event generally coincides with the beginning of the animation to the new map extent. This provides an excellent opportunity to start loading the surf spots while the map is doing its animation thing.

private void Map_ViewChangeStart(object sender, MapEventArgs e)
{
    MapViewSpecification mvs = Map1.TargetView;
    LocationRect bounds = Map1.GetBoundingRectangle(mvs);
    viewModel.LoadSurfSpots(bounds.North, bounds.West, bounds.South, bounds.East);
}

In the Map_ViewChangeStart event, the map’s TargetView property contains the MapViewSpecification of the map extent that the map will be animating (panning or zooming) towards. The method examines the bounding rectangle of the target MapViewSpecification and asks the SurfSpotsViewModel to load the surf spots within that map extent via the LoadSurfSpots method.

Notice that the method just asks the ViewModel to load the surf spots, but it doesn’t expect an immediate response. Later, when the ViewModel has finished loading the data, it fires off an event telling both Views to refresh themselves with the new data. This allows for data to be loaded asynchronously, typically from a remote web service.

The SurfSpotsMapView class has a ViewModel property setter where we wire up the events that are expected to be fired from the ViewModel. This is called when the View is first created:

public SurfSpotsViewModel ViewModel
{
    get { return viewModel; }
    set
    {
        viewModel = value;

        // Wire up the View Model
        viewModel.SurfSpotsLoaded += new EventHandler(SurfSpotsLoadedHandler);
        viewModel.SurfSpotsLoadError += new EventHandler(SurfSpotsLoadErrorHandler);
        viewModel.SelectedSurfSpotChanged += new EventHandler(SelectedSurfSpotChangedHandler);
    }
}

Like the ViewModel, the repository is also asynchronous in nature and the ViewModel’s LoadSurfSpots method simply delegates to an analogous method on the repository. Consider the following ISurfSpotsRespository interface:

public interface ISurfSpotRepository
{
    // Load all surf spots
    void LoadSurfSpots();

    // Load surf spots within the specified extent
    void LoadSurfSpots(double north, double west, double south, double east);

    // Event to fire when surf spots have been loaded
    event EventHandler<SurfSpotEventArgs> SurfSpotLoadingComplete;

    // Event to fire when there is an error loading surf spots
    event EventHandler<SurfSpotErrorEventArgs> SurfSpotLoadingError;
}

When the repository has finished loading the data, it fires the SurfSpotLoadingComplete event back to the ViewModel, which in turn fires its own event back to any listening Views.

To keep the example simple, ISurfSpotRespository is implemented as a mock in-memory repository called InMemorySurfSpotRepository. See the sample code download for the complete implementation. Note that a real web application would most likely load the data from a remote web service. See Johannes Kebeck’s Blog Post Database Connections with the Virtual Earth Silverlight MapControl CTP for a good example of how to do that.

Once the data loading is complete, the SurfSpotsLoadedHandler method of the SurfSpotsMapView class handles adding the new surf spots to the map:

private void SurfSpotsLoadedHandler(object sender, EventArgs e)
{
    surfSpotsLayer.RemoveAllChildren();
    foreach (SurfSpot s in viewModel.SurfSpots)
    {
        Ellipse point = new Ellipse()
        {
            Width = 10,
            Height = 10,
            Fill = new SolidColorBrush(Colors.Red),
            Opacity = 0.65,
            Tag = s
        };
        point.MouseLeftButtonDown += new MouseButtonEventHandler(
            SurfSpotPoint_MouseLeftButtonDown);
        MapLayer.SetMapPosition(point, new Location(s.Latitude, s.Longitude));
        ToolTipService.SetToolTip(point, s.Name);
        surfSpotsLayer.Children.Add(point);
    }
}

In the SurfSpotsListView, keeping the list updated is even easier. The SurfSpots property of the ViewModel is an ObservableCollection<SurfSpot>, so we just need to set the ItemsSource property of inner DataGrid and it will keep itself updated automatically. This happens in the ViewModel property setter for the SurfSpotsListView:

public SurfSpotsViewModel ViewModel
{
    get { return viewModel; }
    set
    {
        viewModel = value;

        // Wire up the View Model
        viewModel.SelectedSurfSpotChanged += new EventHandler(SelectedSurfSpotChangedHandler);
        viewModel.SurfSpotsLoaded += new EventHandler(SurfSpotsLoaded);
        viewModel.SurfSpotsLoadError += new EventHandler(SurfSpotsLoadErrorHandler);

        // Set the items source for the data grid. Since it is an
        // ObservableCollection<> we don't need to handle the SurfSpotsLoaded
        // event. The grid view will automatically keep itself updated.
        DataGrid1.ItemsSource = viewModel.SurfSpots;
    }
}

Unit Tests

Of course, one of the main reasons for using the Model-View-ViewModel pattern is testability. I’ve included a simple unit test of the View Model class in the Tests project to illustrate the concept. This test is modeled after the tests found in Shawn Wildermuth’s sample code. I didn’t create a full array of tests, as it wasn’t necessary for the proof of concept. I’ll leave that as an exercise for the reader.

Wrap Up

This post has presented a proof of concept sample application using the Model-View-ViewModel pattern with the Microsoft Bing Maps (Virtual Earth) Silverlight Map Control CTP. ViewModel synchronization with multiple Views is demonstrated in the sample. While we covered some of the implementation details in this post, there is more to be found in the downloadable sample – so be sure to check it out!

If you would be interested in a follow up post covering some of the additional implementation details, please let me know in the comments.

Hope this helps!

Resources

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen | Modified by Mooglegiant
Creative Commons License This work is licensed under a Creative Commons Attribution 3.0 United States License.

Welcome

James Richards

Hi, I'm James Richards the CTO and co-founder of Artisan Global LLC. We make location-aware mobile apps with maps. I'm the author of QuakeFeed and I helped launch Zaarly at LASW Feb 2011. I also enjoy surfing, snowboarding, golfing, yoga, and music. I love my family: Linda, Sequoya and our cats Remy and Twiggy. Thanks for stopping by, I hope you find something helpful here.

Subscribe by RSS   Follow me on Twitter   Connect on Facebook   View my profile on LinkedIn


Amazon Associates

Some of my posts may contain Amazon Associates links. I only include these links when it makes sense within the context of the article. If you are in the market for one of these items, please consider clicking on an affiliate link to make your purchase. You still get the same great deal from Amazon and it will help me pay for hosting and bandwidth. Thanks!