虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > WindowsPhone/WindowsMobile > Windows Phone笔记(6)使用地图服务

Windows Phone笔记(6)使用地图服务
类别:WindowsPhone/WindowsMobile   作者:码皇   来源:互联网   点击:

现在的智能手机中地图应用已经成为基础功能之外的最重要的功能之一了,在很多应用中经常会使用到地图。在我们前面的Windows Phone笔记中讲到了位置服务,可以通过GPS对手机当前所在位置进行定位,返回当前位置的

现在的智能手机中地图应用已经成为基础功能之外的最重要的功能之一了,在很多应用中经常会使用到地图。在我们前面的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      }

 编译运行,我们输入出发点和终点,程序会首先调用地理编码服务计算出起点和终点的经纬度,然后把他们放在一个集合中,作为参数向路由功能服务发送请求,计算起点和终点的路线信息,最后显示在地图中,下面是程序运行的效果:

   

 

   摘自摘自 晴天猪の博客
 

相关热词搜索: Windows Phone 笔记