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]

      <DefaultTask Name="_default" NavigationPage="MainPage.xaml">
<BackgroundExecution>
<ExecutionType Name="LocationTracking" />
</BackgroundExecution>
</DefaultTask>

然后我们需要注册RunningInBackground事件,打开App.xaml添加事件Application_RunningInBackground,代码如下:

[XAML]

        <!--处理应用程序的生存期事件所需的对象-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"
RunningInBackground="Application_RunningInBackground"/>

在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]

        <!--ContentPanel - 在此处放置其他内容-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<!--地图控件-->
<maps:Map x:Name="MyMap" Center="30.5473, 114.2922" ZoomLevel="10" LandmarksEnabled="true" PedestrianFeaturesEnabled="true" />
<Button Foreground="Red" Content="指定位置" HorizontalAlignment="Left" Margin="295,530,0,0" VerticalAlignment="Top" Click="Button_Click_1" Width="151"/>
<Button Foreground="Red" Content="制图模式" HorizontalAlignment="Left" Margin="10,530,0,0" VerticalAlignment="Top" Click="Button_Click_2"/>
<Button Foreground="Red" Content="颜色模式" HorizontalAlignment="Left" Margin="134,530,0,0" VerticalAlignment="Top" Click="Button_Click_3"/>
<Button Foreground="Red" Content="我的位置" HorizontalAlignment="Left" Margin="10,602,0,0" VerticalAlignment="Top" Click="Button_Click_4"/>
</Grid>
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
{
/// <summary>
/// 把定位位置转换为地图位置
/// </summary>
/// <param name="geocoordinate"></param>
/// <returns></returns>
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]

    <phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="RouteListTemplate">
<TextBlock Text="{Binding}" FontSize="{StaticResource PhoneFontSizeMedium}" Margin="5,5,0,0"/>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot 是包含所有页面内容的根网格-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="地图导航" Grid.Row="0" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,0,0,20"/>
<maps:Map x:Name="MyMap" Grid.Row="1" Center="30.476724, 114.406563" ZoomLevel="13"/>
<TextBlock Text="驾车路线" Grid.Row="2" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,10,0,20"/>
<phone:LongListSelector x:Name="RouteLLS" Grid.Row="3" Background="Transparent" ItemTemplate="{StaticResource RouteListTemplate}" LayoutMode="List"
IsGroupingEnabled="False"/>
</Grid>

[C#]

    public partial class Page1 : PhoneApplicationPage
{
public Page1()
{
InitializeComponent();
this.GetCoordinates();
} RouteQuery MyQuery = null;
GeocodeQuery Mygeocodequery = null; List<GeoCoordinate> MyCoordinates = new List<GeoCoordinate>(); 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<IList<MapLocation>> 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<Route> e)
{
if (e.Error == null)
{
//获取具体的行程路线
Route MyRoute = e.Result;
MapRoute MyMapRoute = new MapRoute(MyRoute);
MyMap.AddRoute(MyMapRoute);
List<string> RouteList = new List<string>();
foreach (RouteLeg leg in MyRoute.Legs)
{
foreach (RouteManeuver maneuver in leg.Maneuvers)
{
RouteList.Add(maneuver.InstructionText);
}
} RouteLLS.ItemsSource = RouteList;
MyQuery.Dispose();
}
} }

Windows phone 8 学习笔记(8) 定位地图导航(转)的更多相关文章

  1. Windows phone 8 学习笔记(8) 定位地图导航

    原文:Windows phone 8 学习笔记(8) 定位地图导航 Windows phone 8 已经不使用自家的bing地图,新地图控件可以指定制图模式.视图等.bing地图的定位误差比较大,在模 ...

  2. Windows phone 8 学习笔记

    Windows phone 8 学习笔记(1) 触控输入  http://www.apkbus.com/android-138547-1-1.html Windows phone 8 学习笔记(2) ...

  3. Windows phone 8 学习笔记(9) 集成

    原文:Windows phone 8 学习笔记(9) 集成 本节整理了之前并没有提到的Windows phone 8 系统相关集成支持,包括选择器.锁定屏幕的.联系人的访问等.选择器列举了若干内置应用 ...

  4. Windows phone 8 学习笔记(7) 设备

    原文:Windows phone 8 学习笔记(7) 设备 本节主要涉及到 Windows phone 8 手机支持的各类设备,包括相机.设备状态,振动装置等.还有各类感应器,包括磁力计.加速度器和陀 ...

  5. Windows phone 8 学习笔记(1) 触控输入

    原文:Windows phone 8 学习笔记(1) 触控输入 Windows phone 8 的应用 与一般的Pc应用在输入方式上最大的不同就是:Windows phone 8主要依靠触控操作.因此 ...

  6. Windows phone 8 学习笔记(5) 图块与通知(转)

    基于metro风格的Windows phone 8 应用提到了图块的概念,它就是指启动菜单中的快速启动图标.一般一个应用必须有一个默认图块,还可以有若干个次要图块.另外,通知与图块的关系比较密切,我们 ...

  7. Windows phone 8 学习笔记(2) 数据文件操作(转)

    Windows phone 8 应用用于数据文件存储访问的位置仅仅限于安装文件夹.本地文件夹(独立存储空间).媒体库和SD卡四个地方.本节主要讲解它们的用法以及相关限制性.另外包括本地数据库的使用方式 ...

  8. Windows phone 8 学习笔记(6) 多任务

    原文:Windows phone 8 学习笔记(6) 多任务 Windows phone 8 是一个单任务操作系统,任何时候都只有一个应用处于活跃状态,这里的多任务是指对后台任务的支持.本节我们先讲讲 ...

  9. Windows phone 8 学习笔记(5) 图块与通知

    原文:Windows phone 8 学习笔记(5) 图块与通知 基于metro风格的Windows phone 8 应用提到了图块的概念,它就是指启动菜单中的快速启动图标.一般一个应用必须有一个默认 ...

随机推荐

  1. suibi

    测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等. 我所了解的模块接口测试大体分为两类:模块接口测试和web接口测试 模块接口测试是单元测试的基础.它主要测试模块的调用 ...

  2. 在tortoiseSVN上将trunk的代码merge到branch上去

    1.进入branch项目的目录 2.右键选择merge 3.下一步 4.选择trunk

  3. js实现未知宽高的元素在指定元素中垂直水平居中

    js实现未知宽高的元素在指定元素中垂直水平居中:本章节介绍一下如何实现未知宽高的元素在指定元素下实现垂直水平居中效果,下面就以span元素为例子,介绍一下如何实现span元素在div中实现水平垂直居中 ...

  4. linux ps命令(转载)

    来源:http://www.cnblogs.com/peida/archive/2012/12/19/2824418.html Linux中的ps命令是Process Status的缩写.ps命令用来 ...

  5. centos5安装在大硬盘上面的问题

    硬盘空间大小: 3TB 原始硬盘是GPT格式的,系统安装现象如下: 此时按 ctrl + alt + F2 ,进入命令行界面,输入如下: 发现 用parted修改硬盘分区格式为msdos,报错!基本可 ...

  6. 20145305 《Java程序设计》实验五

    实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 基于Java Socket实现安全传输 基于TCP实现客户端和服务器,结对编程一人负责客户端,一 ...

  7. log4net 日志写入MongoDB 实现分布式日志

    本人在.net framework 4.5下测试成功,首先需要安装log4mongo-net组件,见https://www.nuget.org/packages/log4mongo-net/ vs20 ...

  8. 常见的MIME类型

    超文本标记语言文本 .htm,.html text/html 普通文本 .txt text/plain GIF图形 .gif image/gif JPEG图形 .ipeg,.jpg image/jpe ...

  9. html 去掉input 获取焦点时的边框

    html中,当input标签获取焦点的时候(例如,当光标放在input框中准备输入值时), input标签外围会出现边框,有的时候我们需要去掉这个边框,可以使用css的outline:none;属性将 ...

  10. OC基础(1)

    Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 *:first-child { margin-top: 0 !important; } body > *:last-chi ...