虽然Bing地图是Windows Phone应用的默认地图服务,但开发者经常希望能够在他们的应用中集成Google地图。尽管这看起来似乎不可能,因为微软提供的地图控制与Bing地图兼容,但实际上,地图控制的灵活性允许展示几乎任何地图,包括Google地图。
地图控制默认使用Bing地图的图像,只需要提供从Bing网站获取的开发者凭据,就可以使用Bing地图。地图控制已经内置了所有基本功能,如缩放和导航。只需要拖放控制,提供凭据,就可以开始使用。
对于Google地图,首先需要理解地图控制的工作方式。它基本上不断地调用一个方法Uri GetUri(int x, int y, int zoomLevel)
,该方法返回一个包含要显示的瓦片图像的Uri。瓦片是一个256x256的图像,由其在网格中的X和Y位置定义,形成特定缩放级别的世界地图。
需要编写一个类,继承自Microsoft.Phone.Controls.Maps.TileSource
,并包含一个重写的Uri GetUri(int x, int y, int zoomLevel)
方法,以显示自定义瓦片,在例子中是Google地图瓦片。
首先,需要定义一个枚举,包含Google地图支持的所有地图模式。将在稍后检查地图的模式时使用这个枚举。
public enum GoogleTileTypes
{
Hybrid,
Physical,
Street,
Satellite,
WaterOverlay
}
接下来,编写上面讨论的类,它将包含Uri GetUri(int x, int y, int zoomLevel)
方法和一些为方便而创建的实用方法。
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 '\0';
}
}
使用以下URL作为Google地图瓦片源:
UriFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}";
其中有以下参数:
接下来,转向XAML部分,在这里实际上定义了地图控制及其层。首先,需要以下两个命名空间:
xmlns:GoogleTileSource="clr-namespace:googlemaps;assembly=googlemaps"
xmlns:MSPCMCore="clr-namespace:Microsoft.Phone.Controls.Maps.Core;assembly=Microsoft.Phone.Controls.Maps"
将地图模式保持为Mercator,这告诉控制不要为地图加载任何默认图像。接下来,在地图控制上放置层,Google地图的瓦片将显示在这些层上。使用了5层,因为要按照用户的选择改变地图的模式。
如果要保持模式静态,只需要一个层。每个层都有其瓦片源,在例子中是类GoogleTile
。
最后,为了为用户提供一些基本功能,如改变模式和缩放,连接了一些事件处理程序。
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--;
}