1.注册Bing Maps API密匙
在Windows Phone开发中,我们可以通过使用Windows Phone中的Map控件,使用微软提供的Bing Maps服务,在程序中使用Bing Maps服务需要获取一个地图应用API的Key,这要求你注册一个Windows Live的账号,这是免费的,而且步骤非常简单(这里是获取Key的地址),使用Windows Live账号登陆后:
点击“Create or View Keys":
填写好相应的表单后就会得到一个属于你自己的Key了。
在后面的程序中你将会使用到它。
下面我们通过是一个简单的示例来了解Map控件是如何进行缩放以及设置它的显示模式:道路模式和航测模式。这是前台页面MainPage.xaml的代码:
<!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <my:Map Name="map1" Height="450" CredentialsProvider="你注册的Key值"> </my:Map> <StackPanel> <Grid> <Button Content="航测模式" HorizontalAlignment="Left" Width="160" Name="btnAerial" Click="btnAerial_Click"></Button> <Button Content="道路模式" HorizontalAlignment="Right" Width="160" Name="btnRoad" Click="btnRoad_Click"></Button> </Grid> </StackPanel> <StackPanel> <Grid> <Button Content="放大" HorizontalAlignment="Left" Width="160" Name="btnZoomIn" Click="btnZoomIn_Click"></Button> <Button Content="缩小" HorizontalAlignment="Right" Width="160" Name="btnZoomOut" Click="btnZoomOut_Click"></Button> </Grid> </StackPanel> </StackPanel> </Grid>
这里给出后台程序MainPage.xaml.cs的处理代码:
/// <summary> /// 放大 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZoomIn_Click(object sender, RoutedEventArgs e) { double zoom; zoom = map1.ZoomLevel; map1.ZoomLevel = ++zoom; } /// <summary> /// 缩小 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZoomOut_Click(object sender, RoutedEventArgs e) { double zoom; zoom = map1.ZoomLevel; map1.ZoomLevel = --zoom; } /// <summary> /// 道路模式 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnRoad_Click(object sender, RoutedEventArgs e) { map1.Mode = new RoadMode(); } /// <summary> /// 航测模式 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnAerial_Click(object sender, RoutedEventArgs e) { map1.Mode = new AerialMode(true);//参数为true的构造函数表示显示地理信息 }
3.在Map中使用位置服务(定位)和图钉(pushpin)
MainPage.xaml:
<!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <my:Map Name="map1" Height="500" VerticalAlignment="Top" CredentialsProvider="你注册的Map Key"/> <Button Content="定位" VerticalAlignment="Bottom" Name="btn_Location" Click="btn_Location_Click"/> </Grid>
后台处理程序,MainPage.xaml.cs:
public partial class MainPage : PhoneApplicationPage { GeoCoordinateWatcher watcher; // 构造函数 public MainPage() { InitializeComponent(); } /// <summary> /// 在地图上定位 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Location_Click(object sender, RoutedEventArgs e) { if (watcher == null) { watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // 采用高精度 watcher.MovementThreshold = 20; // PositionChanged事件之间传送的最小距离 //绑定事件 watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged); //开始从位置服务获取数据 watcher.Start(); } } //检测到位置更改时 //当定位服务已准备就绪并接收数据时,它将开始引发 PositionChanged 事件 void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { Location location = new Location();//实例化一个位置位置类的实例 //将当前的经纬度值赋给位置对象 location.Latitude = e.Position.Location.Latitude; location.Longitude = e.Position.Location.Longitude; Pushpin pushpin = new Pushpin();//实例化一个图钉实例 pushpin.Content = "当前位置"; pushpin.Location = location; this.map1.Children.Add(pushpin);//将图钉显示在地图上 this.map1.SetView(location, 10);//缩放界别为10(1-16),始终将当前位置位于地图中心 } }
4.使用Bing Maps SOAP Services
Bing Maps提供了一组SOAP Services,通过使用这些服务可以使我们能够使我们的应用实现地理位置计算、路径计算等额外的功能。现在让我们一起来了解如何使用其中的两个服务。
地理编码服务可以通过搜索地名来匹配在地图上对应的位置(经度和纬度),或者通过实际位置的经度和纬度来确定对应在地图上的位置。
路由功能服务可以通过计算地点的坐标来显示线路的功能,比如在百度地图中常用的驾车线路功能等。
下面让我们通过一个示例来了解如何使用这些服务,在Windows Phone中实现我们在地图应用中常见的出行路径计算的功能。首先添加前面给出地址的两个服务引用,下面让代码来说话:
MainPage.xaml代码:
<!--LayoutRoot 是包含所有页面内容的根网格--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="0"> <Grid Height="530" VerticalAlignment="Top"> <my:Map Name="map1" CredentialsProvider="Map Key" /> </Grid> </Grid> <Grid Grid.Row="1" > <StackPanel Orientation="Vertical"> <Grid> <TextBlock Text="起点:" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="28" ></TextBlock> <TextBox Width="400" Height="80" HorizontalAlignment="Right" Name="txtStartPath"></TextBox> </Grid> <Grid> <TextBlock Text="终点:" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="28" ></TextBlock> <TextBox Width="400" Height="80" HorizontalAlignment="Right" Name="txtStopPath"></TextBox> </Grid> <Button Height="80" Content="查找路径" FontSize="28" Name="btnQueryPath" Click="btnQueryPath_Click"></Button> </StackPanel> </Grid> </Grid>
后台处理程序,代码比较长:
1 View Code 2 public partial class MainPage : PhoneApplicationPage 3 { 4 // 构造函数 5 public MainPage() 6 { 7 InitializeComponent(); 8 } 9 10 /// <summary> 11 /// 查询路线 12 /// </summary> 13 /// <param name="sender"></param> 14 /// <param name="e"></param> 15 private void btnQueryPath_Click(object sender, RoutedEventArgs e) 16 { 17 geocodeResults = new GeocodeResult[2]; 18 19 GetGeocodeAsync(this.txtStartPath.Text, 0);//起点 20 GetGeocodeAsync(this.txtStopPath.Text, 1);//终点 21 } 22 23 /// <summary> 24 /// 根据地名查询地理坐标 25 /// </summary> 26 /// <param name="strGeocodeInfo"></param> 27 public void GetGeocodeAsync(string strAddress, int waypointIndex) 28 { 29 try 30 { 31 //实例化GeocodeService客户端对象 32 GeocodeServiceClient client = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService"); 33 //绑定事件,查询完成后发生 34 client.GeocodeCompleted += new EventHandler<GeocodeCompletedEventArgs>(OnGeocodeCompleted); 35 36 //创建一个Geocode检索请求 37 GeocodeRequest request = new GeocodeRequest(); 38 //设置地图证书 39 request.Credentials = new Microsoft.Phone.Controls.Maps.Credentials(); 40 request.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)map1.CredentialsProvider).ApplicationId; 41 //设置检索条件 42 request.Query = strAddress; 43 //异步调用Geocode服务方法 44 client.GeocodeAsync(request, waypointIndex); 45 } 46 catch (Exception ex) 47 { 48 MessageBox.Show("地理信息编码服务解析过程中出现错误."); 49 } 50 } 51 52 //使用全局变量来存储起点和终点的位置信息 53 internal GeocodeResult[] geocodeResults; 54 55 /// <summary> 56 /// 当检索地理信息完成后的回调函数 57 /// </summary> 58 /// <param name="sender"></param> 59 /// <param name="e"></param> 60 private void OnGeocodeCompleted(object sender, GeocodeCompletedEventArgs e) 61 { 62 if (e.Error == null) 63 { 64 int waypointIndex = System.Convert.ToInt32(e.UserState); 65 geocodeResults[waypointIndex] = e.Result.Results[0]; 66 67 bool doneGeocoding = true; 68 69 foreach (GeocodeService.GeocodeResult gr in geocodeResults) 70 { 71 if (gr == null) 72 { 73 doneGeocoding = false; 74 } 75 } 76 77 //当起点和终点位置查询都已经完成时,调用Route服务查询路线 78 if (doneGeocoding) 79 { 80 CalculateRoute(geocodeResults); 81 } 82 } 83 } 84 85 /// <summary> 86 /// 根据起点终点坐标查询,使用路由服务查询路线 87 /// </summary> 88 /// <param name="results"></param> 89 private void CalculateRoute(GeocodeResult[] results) 90 { 91 RouteServiceClient routeService = new RouteServiceClient("BasicHttpBinding_IRouteService"); 92 //绑定事件回调函数 93 routeService.CalculateRouteCompleted += new EventHandler<RouteService.CalculateRouteCompletedEventArgs>(routeService_CalculateRouteCompleted); 94 95 // 设置地图证书 96 RouteRequest routeRequest = new RouteRequest(); 97 routeRequest.Credentials = new Credentials(); 98 routeRequest.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)map1.CredentialsProvider).ApplicationId; 99 100 //实例化一个路由节点 101 routeRequest.Options = new RouteOptions(); 102 routeRequest.Options.RoutePathType = RoutePathType.Points; 103 104 //将保存Geocode服务查询结果的变量赋给到Route服务的waypoints属性中 105 routeRequest.Waypoints = new ObservableCollection<RouteService.Waypoint>(); 106 foreach (GeocodeResult result in results) 107 { 108 routeRequest.Waypoints.Add(GeocodeResultToWaypoint(result)); 109 } 110 111 //向路由服务发送异步请求 112 routeService.CalculateRouteAsync(routeRequest); 113 114 } 115 116 /// <summary> 117 /// 解析Geocode服务返回的数据 118 /// </summary> 119 /// <param name="result"></param> 120 /// <returns></returns> 121 private Waypoint GeocodeResultToWaypoint(GeocodeResult result) 122 { 123 Waypoint waypoint = new Waypoint(); 124 waypoint.Description = result.DisplayName;//显示名称 125 waypoint.Location = new Location(); 126 waypoint.Location.Latitude = result.Locations[0].Latitude;//纬度 127 waypoint.Location.Longitude = result.Locations[0].Longitude;//精度 128 return waypoint; 129 } 130 131 /// <summary> 132 /// 当CalculateRoute方法请求完成后的回调函数 133 /// </summary> 134 /// <param name="sender"></param> 135 /// <param name="e"></param> 136 private void routeService_CalculateRouteCompleted(object sender, RouteService.CalculateRouteCompletedEventArgs e) 137 { 138 try 139 { 140 //如果路由服务成功返回来路线信息,就把路线绘制到地图上 141 if ((e.Result.ResponseSummary.StatusCode == RouteService.ResponseStatusCode.Success) & (e.Result.Result.Legs.Count != 0)) 142 { 143 //设置你想要绘制路线的信息 144 Color routeColor = Colors.Red; 145 SolidColorBrush routeBrush = new SolidColorBrush(routeColor); 146 MapPolyline routeLine = new MapPolyline(); 147 routeLine.Locations = new LocationCollection(); 148 routeLine.Stroke = routeBrush; 149 routeLine.Opacity = 0.6; 150 routeLine.StrokeThickness = 5.0; 151 152 // 循环读取返回的路线信息 153 foreach (Location p in e.Result.Result.RoutePath.Points) 154 { 155 Location location = new Location() 156 { 157 Longitude = p.Longitude, 158 Latitude = p.Latitude 159 }; 160 routeLine.Locations.Add(location); 161 } 162 // 增加一个地图图层来绘制路线 163 MapLayer myRouteLayer = new MapLayer(); 164 map1.Children.Add(myRouteLayer); 165 166 //把路线添加到图层中来 167 myRouteLayer.Children.Add(routeLine); 168 169 //遍历处理服务调用接口中的路程行程点,将各个行程点上绘制一个红色圆形标记 170 foreach (GeocodeService.GeocodeResult gr in geocodeResults) 171 { 172 Ellipse point = new Ellipse(); 173 point.Width = 10; 174 point.Height = 10; 175 point.Fill = new SolidColorBrush(Colors.Red); 176 point.Opacity = 0.65; 177 Location location = new Location() 178 { 179 Latitude = gr.Locations[0].Latitude, 180 Longitude = gr.Locations[0].Longitude 181 }; 182 //将图层添加到地图制定的位置 183 myRouteLayer.AddChild(point, location); 184 } 185 //包含整个绘制路线的矩形 186 var routeModel = new RouteModel(e.Result.Result.RoutePath.Points); 187 LocationRect rect = LocationRect.CreateLocationRect(routeModel.Locations); 188 189 //将路线显示在视图中间 190 map1.SetView(rect); 191 } 192 } 193 catch (Exception ex) 194 { 195 MessageBox.Show("路由服务解析过程中出现错误."); 196 } 197 } 198 } 199 /// <summary> 200 /// 代表路线的数据模型 201 /// </summary> 202 public class RouteModel 203 { 204 private readonly LocationCollection _locations; 205 206 /// <summary> 207 /// 得到这个路线的位置集合 208 /// </summary> 209 public ICollection<GeoCoordinate> Locations 210 { 211 get { return _locations; } 212 } 213 214 /// <summary> 215 ///初始化该类型的一个新的实例 216 /// </summary> 217 /// <param name="locations">一个Loaction的集合</param> 218 public RouteModel(ICollection<Location> locations) 219 { 220 _locations = new LocationCollection(); 221 foreach (Location location in locations) 222 { 223 _locations.Add(location); 224 } 225 } 226 }
编译运行,我们输入出发点和终点,程序会首先调用地理编码服务计算出起点和终点的经纬度,然后把他们放在一个集合中,作为参数向路由功能服务发送请求,计算起点和终点的路线信息,最后显示在地图中,下面是程序运行的效果:
附:源码下载
《Programming Windows Phone 7 Microsoft Silverlight Edition》
作者:晴天猪
出处:http://www.cnblogs.com/IPrograming
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。