| 
 | 
	
 
 
  Windows phone 8 已经不使用自家的bing地图,新地图控件可以指定制图模式、视图等。bing地图的定位误差比较大,在模拟器中测试新地图貌似比较理想。本节主要讲解下位置服务以及新地图控件的使用。 
  快速导航: 
    一、定位服务 
    二、地图和导航 
 
 
一、定位服务 
  通过手机定位服务可以开发利用手机地理位置的应用。我们可以通过应用监视手机行踪,配合地图使用可以用于导航等。定位服务可以及时取得手机地理位置,也可以持续跟踪手机移动,还可以在后台运行。 
 
1. 立即获取当前位置 
  我们可以通过一次操作获取当前位置,下面的代码演示了实现的方法。 
 
[C#] 
 
 
 private async void OneShotLocation_Click(object sender, RoutedEventArgs e) 
{ 
//地理位置访问服务 
Geolocator geolocator = new Geolocator(); 
//定义精度,米为单位 
geolocator.DesiredAccuracyInMeters = 1; 
try 
{ 
//开始获取当前位置的经纬度 
Geoposition geoposition = await geolocator.GetGeopositionAsync(); 
LatitudeTextBlock.Text = "经度:" + geoposition.Coordinate.Latitude.ToString("0.00"); 
LongitudeTextBlock.Text = "纬度:" + geoposition.Coordinate.Longitude.ToString("0.00"); 
} 
catch (Exception ex) 
{ 
if ((uint)ex.HResult == 0x80004004) 
{ 
StatusTextBlock.Text = "系统设置关闭了位置服务."; 
} 
} 
} 
 
   
 
2. 持续跟踪位置信息 
  如果开启持续跟踪手机位置,当手机移动距离超出设定距离时,就会触发位置改变事件,这个时候我们就可以通过环境信息计算出手机的行动轨迹,速度方向等。下面演示了如何持续跟踪。 
 
[C#] 
 
 
Geolocator geolocator = null; 
bool tracking = false; 
private void TrackLocation_Click(object sender, RoutedEventArgs e) 
{ 
if (!tracking) 
{ 
//地理位置访问服务 
geolocator = new Geolocator(); 
//精度级别 
geolocator.DesiredAccuracy = PositionAccuracy.High; 
//超过多少米引发位置改变事件 
geolocator.MovementThreshold = 100; 
//功能状态改变时 
geolocator.StatusChanged += geolocator_StatusChanged; 
//位置改变时 
geolocator.PositionChanged += geolocator_PositionChanged; 
tracking = true; 
TrackLocationButton.Content = "停止跟踪"; 
} 
else 
{ 
geolocator.PositionChanged -= geolocator_PositionChanged; 
geolocator.StatusChanged -= geolocator_StatusChanged; 
geolocator = null; 
tracking = false; 
TrackLocationButton.Content = "跟踪位置"; 
StatusTextBlock.Text = "停止"; 
} 
} 
void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args) 
{ 
string status = ""; 
switch (args.Status) 
{ 
case PositionStatus.Disabled: 
status = "位置服务设置被禁用"; 
break; 
case PositionStatus.Initializing: 
status = "正在初始化"; 
break; 
case PositionStatus.NoData: 
status = "无数据"; 
break; 
case PositionStatus.Ready: 
status = "已准备"; 
break; 
case PositionStatus.NotAvailable: 
status = "无法使用"; 
break; 
case PositionStatus.NotInitialized: 
break; 
} 
Dispatcher.BeginInvoke(() => 
{ 
StatusTextBlock.Text = status; 
}); 
} 
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args) 
{ 
Dispatcher.BeginInvoke(() => 
{ 
LatitudeTextBlock.Text = "经度:" + args.Position.Coordinate.Latitude.ToString("0.00"); 
LongitudeTextBlock.Text = "纬度:" + args.Position.Coordinate.Longitude.ToString("0.00"); 
}); 
} 
 
   
 
3. 在后台持续跟踪 
  位置跟踪可以作为服务在后台运行,这个时候我们不需要更新UI,为了使我们的应用可以作为服务运行,我们需要右键打开清单文件,选择用XML文本编辑器的方式,替换DefaultTask节点为如下信息: 
 
[XML] 
 
 
       
 
 
 
 
 
  然后我们需要注册RunningInBackground事件,打开App.xaml添加事件Application_RunningInBackground,代码如下: 
 
[XAML] 
 
 
         
 
 
  在App.xaml.cs中添加静态变量RunningInBackground和Geolocator,当Application_RunningInBackground事件时RunningInBackground为true,当Application_Activated事件时,RunningInBackground为false。代码如下: 
 
[C#] 
 
 
//确定应用是否在后台运行 
public static bool RunningInBackground { get; set; } 
//提供对当前地理位置的访问 
public static Geolocator Geolocator { get; set; } 
// 激活应用程序(置于前台)时执行的代码 
// 此代码在首次启动应用程序时不执行 
private void Application_Activated(object sender, ActivatedEventArgs e) 
{ 
RunningInBackground = false; 
} 
private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args) 
{ 
RunningInBackground = true; 
} 
 
  在mainpage中添加如下代码: 
 
[C#] 
 
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
if (App.Geolocator == null) 
{ 
App.Geolocator = new Geolocator(); 
App.Geolocator.DesiredAccuracy = PositionAccuracy.High; 
App.Geolocator.MovementThreshold = 100; 
App.Geolocator.PositionChanged += geolocator_PositionChanged; 
} 
} 
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args) 
{ 
if (!App.RunningInBackground) 
{ 
Dispatcher.BeginInvoke(() => 
{ 
LatitudeTextBlock.Text = "经度:" + args.Position.Coordinate.Latitude.ToString("0.00"); 
LongitudeTextBlock.Text = "纬度:" + args.Position.Coordinate.Longitude.ToString("0.00"); 
}); 
} 
else 
{ 
Microsoft.Phone.Shell.ShellToast toast = new Microsoft.Phone.Shell.ShellToast(); 
toast.Content = args.Position.Coordinate.Latitude.ToString("0.00") + "," + args.Position.Coordinate.Longitude.ToString("0.00"); 
toast.Title = "位置:"; 
toast.NavigationUri = new Uri("/Page1.xaml", UriKind.Relative); 
toast.Show(); 
} 
} 
 
   
 
二、地图和导航 
  要用到新地图控件,需要先注册,在phone:PhoneApplicationPage注册标识。 
 
[XAML] 
 
 
xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps" 
 
1.引入地图控件 
  在XAML中添加如下代码即可引入控件。我们看到Center就是指当前地图中心点的经纬度;ZoomLevel就是缩放级别; LandmarksEnabled 属性设置为 true 以在 Map 控件上显示地标; PedestrianFeaturesEnabled 设置为 true,以显示步行街构造。 
 
[XAML] 
 
 
         
 
 
 
 
 
 
 
 
 
   
 
2.设置制图模式 
  在制图模式中有四个选项,分别如下: 
    Road:显示正常的默认二维地图。 
    Aerial:显示航测图。  
    Hybrid:显示与道路和标签重叠的地图的“航测”视图。  
    Terrain:为显示的高地和水域构造(例如高山和河流)显示自然地形图像。 
  下面看看如何切换。 
 
[C#] 
 
 
//切换制图模式 
private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
switch (MyMap.CartographicMode) 
{ 
case MapCartographicMode.Aerial: 
MyMap.CartographicMode = MapCartographicMode.Hybrid; 
break; 
case MapCartographicMode.Hybrid: 
MyMap.CartographicMode = MapCartographicMode.Road; 
break; 
case MapCartographicMode.Road: 
MyMap.CartographicMode = MapCartographicMode.Terrain; 
break; 
case MapCartographicMode.Terrain: 
MyMap.CartographicMode = MapCartographicMode.Aerial; 
break; 
} 
} 
 
   
 
3.设置颜色模式 
  颜色分为明和暗两种,我们看看如何实现。 
 
[C#] 
 
 
//切换颜色模式 
private void Button_Click_3(object sender, RoutedEventArgs e) 
{ 
if (MyMap.ColorMode == MapColorMode.Light) 
MyMap.ColorMode = MapColorMode.Dark; 
else MyMap.ColorMode = MapColorMode.Light; 
} 
 
   
 
4.指定新视角位置 
  我们可以通过编程方式切换视角位置到新的经纬度,并可以指定切换时的过渡效果,这里指定的是抛物线的方式。 
 
[C#] 
 
 
private void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
//以抛物线的方式,把视角定位到光谷软件园中心湖上空。 
MyMap.SetView(new GeoCoordinate(30.476724, 114.406563), 16, MapAnimationKind.Parabolic); 
} 
 
   
 
5.定位我的位置并标记 
  把地图定位到我的当前位置。这个时候就需要借助定位的功能,通过定位功能获取到的经纬度实例类型不一样,需要预先做一个转换。转换类CoordinateConverter如下。 
 
[C#] 
 
 
public static class CoordinateConverter 
{ 
///  
/// 把定位位置转换为地图位置 
///  
///  
///  
public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate) 
{ 
return new GeoCoordinate 
( 
geocoordinate.Latitude, 
geocoordinate.Longitude, 
geocoordinate.Altitude ?? Double.NaN, 
geocoordinate.Accuracy, 
geocoordinate.AltitudeAccuracy ?? Double.NaN, 
geocoordinate.Speed ?? Double.NaN, 
geocoordinate.Heading ?? Double.NaN 
); 
} 
} 
 
  然后,我们需要在地图上画一个小正方形标记我的当前位置,并把地图定位到这里。 
 
[C#] 
 
 
//添加其他控件到地图,标识我的当前位置 
private async void Button_Click_4(object sender, RoutedEventArgs e) 
{ 
//获取我的地理位置 
Geolocator myGeolocator = new Geolocator(); 
//精度 
myGeolocator.DesiredAccuracyInMeters = 1; 
Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync(); 
Geocoordinate myGeocoordinate = myGeoposition.Coordinate; 
//转换经纬度GeoCoordinate 
GeoCoordinate myGeoCoordinate =  CoordinateConverter.ConvertGeocoordinate(myGeocoordinate); 
//MessageBox.Show(myGeoCoordinate.ToString()); 
//定位地图到我的位置 
MyMap.SetView(myGeoCoordinate, 16, MapAnimationKind.Parabolic); 
//画一个正方形,然后渲染在地图的我的当前位置上 
Rectangle MyRectangle = new Rectangle(); 
MyRectangle.Fill = new SolidColorBrush(Colors.Black); 
MyRectangle.Height = 20; 
MyRectangle.Width = 20; 
MapOverlay MyOverlay = new MapOverlay(); 
MyOverlay.Content = MyRectangle; 
MyOverlay.GeoCoordinate = myGeoCoordinate; 
MyOverlay.PositionOrigin = new Point(0, 0.5); 
MapLayer MyLayer = new MapLayer(); 
MyLayer.Add(MyOverlay); 
MyMap.Layers.Add(MyLayer); 
} 
 
   
 
6.获取行车路线 
  我们还可以通过定位和地图实现导航的功能,下面演示了,从我的当前位置(光谷软件园)到指定的位置(光谷创业街)如何行车。 
 
[XAML] 
 
 
     
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   
 
[C#] 
 
 
    public partial class Page1 : PhoneApplicationPage 
{ 
public Page1() 
{ 
InitializeComponent(); 
this.GetCoordinates(); 
} 
RouteQuery MyQuery = null; 
GeocodeQuery Mygeocodequery = null; 
List MyCoordinates = new List(); 
private async void GetCoordinates() 
{ 
Geolocator MyGeolocator = new Geolocator(); 
MyGeolocator.DesiredAccuracyInMeters = 5; 
Geoposition MyGeoPosition = null; 
try 
{ 
MyGeoPosition = await MyGeolocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10)); 
} 
catch (UnauthorizedAccessException) 
{ 
MessageBox.Show("系统设置已关闭位置服务。"); 
} 
catch (Exception ex) 
{ 
} 
MyCoordinates.Add(new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude)); 
 
Mygeocodequery = new GeocodeQuery(); 
Mygeocodequery.SearchTerm = "光谷创业街"; 
Mygeocodequery.GeoCoordinate = new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude); 
Mygeocodequery.QueryCompleted += Mygeocodequery_QueryCompleted; 
Mygeocodequery.QueryAsync(); 
 
} 
void Mygeocodequery_QueryCompleted(object sender, QueryCompletedEventArgs e) 
{ 
if (e.Error == null) 
{ 
MyQuery = new RouteQuery(); 
MyCoordinates.Add(e.Result[0].GeoCoordinate); 
MyQuery.Waypoints = MyCoordinates; 
MyQuery.QueryCompleted += MyQuery_QueryCompleted; 
MyQuery.QueryAsync(); 
Mygeocodequery.Dispose(); 
} 
} 
void MyQuery_QueryCompleted(object sender, QueryCompletedEventArgs e) 
{ 
if (e.Error == null) 
{ 
//获取具体的行程路线 
Route MyRoute = e.Result; 
MapRoute MyMapRoute = new MapRoute(MyRoute); 
MyMap.AddRoute(MyMapRoute); 
List RouteList = new List(); 
foreach (RouteLeg leg in MyRoute.Legs) 
{ 
foreach (RouteManeuver maneuver in leg.Maneuvers) 
{ 
RouteList.Add(maneuver.InstructionText); 
} 
} 
RouteLLS.ItemsSource = RouteList; 
MyQuery.Dispose(); 
} 
} 
} 
 
   
 
 
作者:[Lipan] 
出处:[http://www.iyunv.com/lipan/] 
版权声明:本文的版权归作者与博客园共有。转载时须注明原文出处以及作者,并保留原文指向型链接,不得更改原文内容。否则作者将保留追究其法律责任。 
 
 
《上一篇:Windows phone 8 学习笔记 设备 
系列目录 
下一篇:Windows phone 8 学习笔记 集成》 |   
 
 
 
 | 
  
 |