Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Google Maps for Windows Phone 7 using Bing Map Control

0.00/5 (No votes)
3 Feb 2011 4  
This article covers the way we could use Google Map using the Map Control shipped by Microsoft with Windows Phone 7 Developer Tools
main.PNG

Introduction

Microsoft launched Bing Maps in recent times which is a direct competitor to Google Maps. Bing Maps being relatively new has of course less data and lesser depth in Maps than Google Maps which is in this field for quite a few years. Often, developers want to incorporate Google Maps in their Windows Phone application which seems quite impossible as the Map Control provided by Microsoft is compatible with Bing Maps.

But the thing that we don't know is that Map Control is so flexible that we could display almost any Map on it (thanks to Microsoft for providing us the flexibility). So in this manner we are not bound to show just Bing Maps but we could also use any other map like Google Maps which is covered in this article.

Background

Basically Map Control is shipped with default imagery of Bing Maps for which we only need to provide Developer Credentials available from Bing Website and we are ready to use the Bing Maps. Map Control has all the basic functionality already built in like zooming and navigating into the Map. All we need is to just drop the control, provide credentials and here we go.

Using the Code

For Google Maps, we need to first understand the way Map Control works, well it basically continuously calls a method Uri GetUri(int x, int y, int zoomLevel) which returns a Uri which contains the image of the tile to be displayed. A tile is an image of 256x256 defined by its X and Y position in the grid forming the map of the world on a specific zoom level.

Uri GetUri(int x, int y, int zoomLevel)

All we have to do is to write a class that inherits from Microsoft.Phone.Controls.Maps.TileSource that contains a overridden method Uri GetUri(int x, int y, int zoomLevel) which will display our custom tile which in our case is Google Maps Tile.

First, we need to define an Enum that contains all the modes of maps that Google Maps supports. We will use this Enum later when we will inspect the mode of our Map.

public enum GoogleTileTypes
    {
        Hybrid,
        Physical,
        Street,
        Satellite,
        WaterOverlay
    }

Next we move on towards writing the class that we discussed above that will contain Uri GetUri(int x, int y, int zoomLevel) and some utility methods that we have created for our convenience.

public class GoogleTile : Microsoft.Phone.Controls.Maps.TileSource
    {
        private int _server;
        private char _mapmode;
        private GoogleTileTypes _tiletypes;

        public GoogleTileTypes TileTypes
        {
            get { return _tiletypes; }
            set
            {
                _tiletypes = value;
                MapMode = MapModeConverter(value);
            }
        }

        public char MapMode
        {
            get { return _mapmode; }
            set { _mapmode = value; }
        }

        public int Server
        {
            get { return _server; }
            set { _server = value; }
        }

        public GoogleTile()
        {
            UriFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}";
            Server = 0;
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            if (zoomLevel > 0)
            {
                var Url = string.Format(UriFormat, Server, MapMode, zoomLevel, x, y);
                return new Uri(Url);
            }
            return null;
        }

        private char MapModeConverter(GoogleTileTypes tiletype)
        {
            switch (tiletype)
            {
                case GoogleTileTypes.Hybrid:
                    {
                        return 'y';
                    }
                case GoogleTileTypes.Physical:
                    {
                        return 't';
                    }
                case GoogleTileTypes.Satellite:
                    {
                        return 's';
                    }
                case GoogleTileTypes.Street:
                    {
                        return 'm';
                    }
                case GoogleTileTypes.WaterOverlay:
                    {
                        return 'r';
                    }
            }
            return ' ';
        }
    }

We use the following URL as our Google Tile Source:

UriFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}";

Where we have the following parameters:

  • {0} refers to the server number which we had kept y to 1
  • {1} refers to the character code of the mode of the map
  • {2} refers to the zoom level of the map
  • {3} refers to the x cordinate of the map
  • {4} refers to y cordinate of the map

Now, we move on towards the XAML part where we actually define the Map Control and its layers. First, we need the following two namespaces to MainPage.xaml:

xmlns:GoogleTileSource="clr-namespace:googlemaps;assembly=googlemaps"
xmlns:MSPCMCore="clr-namespace:Microsoft.Phone.Controls.Maps.Core;
	assembly=Microsoft.Phone.Controls.Maps"

We will keep or Map Mode to Mercator which tells the control not to load any default imagery for the Map. Next, we place layers on the Map Control on which Tiles of Google Maps will be displayed. We have used 5 layers as we want to change the Mode of Map as per user's selection of RadioButtons. One could also show more than one layer at the same time by playing around with the Opacity property of different layers. If you want to keep the Mode static, you will only be needing one layer. Each layer has its Tile Source which in this case is the class GoogleTile.

<Microsoft_Phone_Controls_Maps:Map Name="googlemap" Margin="0,161,0,0" 
	CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" 
	ScaleVisibility="Visible" CredentialsProvider=
		"ApBXPZf5IR94SLXE8nh5FYsb5WHKrH1XPY7428-EqQudseivcWhCROIJvGmtnkAV">
    <Microsoft_Phone_Controls_Maps:Map.Mode>
        <MSPCMCore:MercatorMode/>
    </Microsoft_Phone_Controls_Maps:Map.Mode>
    <Microsoft_Phone_Controls_Maps:MapTileLayer Name="street" Margin="0,0,0,32">
        <Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
            <GoogleTileSource:GoogleTile TileTypes="Street"/>
        </Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
    </Microsoft_Phone_Controls_Maps:MapTileLayer>
    <Microsoft_Phone_Controls_Maps:MapTileLayer Visibility="Collapsed" 
		Name="wateroverlay" Margin="0,0,0,32">
        <Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
            <GoogleTileSource:GoogleTile TileTypes="WaterOverlay"/>
        </Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
    </Microsoft_Phone_Controls_Maps:MapTileLayer>
    <Microsoft_Phone_Controls_Maps:MapTileLayer Visibility="Collapsed" 
		Name="hybrid" Margin="0,0,0,32">
        <Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
            <GoogleTileSource:GoogleTile TileTypes="Hybrid"/>
        </Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
    </Microsoft_Phone_Controls_Maps:MapTileLayer>
    <Microsoft_Phone_Controls_Maps:MapTileLayer Visibility="Collapsed" 
		Name="satellite" Margin="0,0,0,32">
        <Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
            <GoogleTileSource:GoogleTile TileTypes="Satellite"/>
        </Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
    </Microsoft_Phone_Controls_Maps:MapTileLayer>
    <Microsoft_Phone_Controls_Maps:MapTileLayer Visibility="Collapsed" 
		Name="physical" Margin="0,0,0,32">
        <Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>

            <GoogleTileSource:GoogleTile TileTypes="Physical"/>
        </Microsoft_Phone_Controls_Maps:MapTileLayer.TileSources>
    </Microsoft_Phone_Controls_Maps:MapTileLayer>
</Microsoft_Phone_Controls_Maps:Map>

Finally to provide users with some basic functionality of changing Mode and Zooming in and out, we wire up some event handlers.

private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (h.IsChecked == true)
            {
                hybrid.Visibility = Visibility.Visible;
                satellite.Visibility = Visibility.Collapsed;
                street.Visibility = Visibility.Collapsed;
                physical.Visibility = Visibility.Collapsed;
                wateroverlay.Visibility = Visibility.Collapsed;
            }
            else if (st.IsChecked == true)
            {
                hybrid.Visibility = Visibility.Collapsed;
                satellite.Visibility = Visibility.Collapsed;
                street.Visibility = Visibility.Visible;
                physical.Visibility = Visibility.Collapsed;
                wateroverlay.Visibility = Visibility.Collapsed;
            }
            else if (sl.IsChecked == true)
            {
                hybrid.Visibility = Visibility.Collapsed;
                satellite.Visibility = Visibility.Visible;
                street.Visibility = Visibility.Collapsed;
                physical.Visibility = Visibility.Collapsed;
                wateroverlay.Visibility = Visibility.Collapsed;
            }
            else if (p.IsChecked == true)
            {
                hybrid.Visibility = Visibility.Collapsed;
                satellite.Visibility = Visibility.Collapsed;
                street.Visibility = Visibility.Collapsed;
                physical.Visibility = Visibility.Visible;
                wateroverlay.Visibility = Visibility.Collapsed;
            }
            else
            {
                hybrid.Visibility = Visibility.Collapsed;
                satellite.Visibility = Visibility.Collapsed;
                street.Visibility = Visibility.Collapsed;
                physical.Visibility = Visibility.Collapsed;
                wateroverlay.Visibility = Visibility.Visible;
            }
        }

        private void ButtonZoomIn_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            googlemap.ZoomLevel++;
        }

        private void ButtonZoomOut_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            googlemap.ZoomLevel--;
        }

So we are ready to take off with just a few lines of code, we are now able to use Google Maps with Bing Map Control provided by Microsoft in Windows Phone Developer tools (thanks to Microsoft for flexible and generic nature of the Map Control).

hybrid.PNG physical.PNG wateroverlay.PNG

street.PNG satellite.PNG

Points of Interest

In future, I plan to provide a more detailed tutorial containing all the features that Google Map provides including directions and routes.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here