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