Windows Phone 8 中的 GeocodeQuery 类。






4.31/5 (4投票s)
正如前一篇文章所述,地理定位是移动设备及其他设备中最常用的功能之一,通过它可以检索我们所在位置的信息,应用程序也可以利用它来获取其他信息,例如餐厅
引言
正如上一篇文章所述,地理定位是移动设备及其他设备中最常用的功能之一,通过它可以检索我们所在位置的信息,应用程序也可以利用它来获取其他信息,例如餐厅、酒店、名胜古迹以及许多其他场景。我们讨论了 ReverseGeocodeQuery 类,它允许您将纬度和经度值转换为地址。在这第三篇文章中,我们将继续深入研究地理定位服务。这次我们将学习如何将地址转换为坐标,即纬度和经度,以便在 Nokia Maps 控件中显示我们的位置或输入地点或城市的名称。
GeocodeQuery 类
除了 Windows.Devices.Geolocation 和 Microsoft.Phone.Maps.Services 命名空间中的 Geolocator 和 ReverseGeocodeQuery 类之外,Windows 运行时还为我们开发者提供了另一个重要类,即 GeocodeQuery 类。后者的操作原理与 ReverseGeocodeQuery 类相同,即转换,但区别在于在这种情况下,它是将地址转换为纬度和经度坐标,然后用于各种目的。现在,在我们使用代码示例之前,让我们先分析一下 GeocodeQuery 类。
与之前的文章一样,我们来看一下主要的方法、属性以及唯一的事件。对于那些关注了上一篇文章的读者,会注意到属性方面的差异。我们有一个 SearchTerm 属性。
属性
- GeoCoordinate
- SearchTerm
最常用的方法
- QueryAsync()
唯一的事件
- QueryCompleted
属性
与 ReverseGeocodeQuery 不同,GeoCoordinate 必须分配默认值,建议纬度和经度都设为零,以避免在首次搜索位置时应用程序崩溃。我们将在示例代码中看到如何实现这一点。
SearchTerm,通过输入地点或兴趣点,此属性意味着当 QueryCompleted 事件发生时,整个内容将被转换为纬度和经度。需要注意的一点是,搜索词中不要包含空格,否则搜索将失败,从而可能导致应用程序崩溃。例如,如果您想输入“Turi n”而不是“Turin”,或者输入“Novi Ligure”,在后一种情况下,搜索将正常开始,因为在搜索阶段肯定会找到它,因为它是一个意大利城镇,而在前一种情况下,应用程序将崩溃,正是出于上述原因。
方法
与 ReverseGeocodeQuery 类一样,QueryAsync() 方法在被调用时执行查询,但这次是基于我们输入并分配给 SearchTerm 属性的时间,结果是纬度和经度坐标。请注意,尽管此方法使用 Async 结尾调用,但它是异步执行的,并且由于它是 void 类型,因此不基于 Async/Await 模式。例如,一个 void 方法在执行时返回 null,就像调用 Int 类型的方法一样。
事件
同样,唯一的事件是 QueryCompleted,在查询完成时执行;它返回所有与地址相关的数据,以及我们需要的 GeoCoordinate 类型的数据,其中将包含 Latitude 和 Longitude 属性,所有这些都包含在 IList
- Cancelled:布尔类型,用于了解异步操作何时以及是否被取消。
- Error:也是布尔类型,在查询执行过程中发生错误时很有用,事实上,从此属性中,您将获得一个 AsyncCompletedEventArgs 类型的对象,其中包含发生的错误。
- Result:我们之前已经描述过,换句话说,查询结果是一个 IList
类型的集合。 - UserState:对象类型属性,它返回正在运行的异步任务的唯一标识符。
将地址转换为纬度和经度。
到目前为止,我们快速概览了 GeocodeQuery 类,即对最常用的方法、属性以及 QueryCompleted 事件进行了简要分析。有关该主题的更多详细信息,请参考 MSDN Library 的官方文档链接。
从上一篇文章中创建的示例开始。前面测试的应用程序结构如下。
使用上一篇文章中的 ReverseGeocodeQuery 类,它可以检测到您在图片中看到的所有数据,并通过其 Information.Address 属性,我们排序
- 城市
- 国家
- CountryCode
- 门牌号
- 邮政编码
- 状态
- 街道
目前这是图形界面表示的 XAML 代码。这是图形界面表示的 XAML 代码。
<!--ContentPanel - inserire ulteriore contenuto qui-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<StackPanel>
<TextBlock Text="City "/>
<TextBlock Text="Country "/>
<TextBlock Text="CountryCode "/>
<TextBlock Text="HouseNumber "/>
<TextBlock Text="PostalCode "/>
<TextBlock Text="State "/>
<TextBlock Text="Street "/>
</StackPanel>
<StackPanel>
<TextBlock x:Name="tbkCity"/>
<TextBlock x:Name="tbkCountry"/>
<TextBlock x:Name="tbkCountryCode"/>
<TextBlock x:Name="tbkHouseNumber"/>
<TextBlock x:Name="tbkPostalCode"/>
<TextBlock x:Name="tbkState"/>
<TextBlock x:Name="tbkStreet"/>
</StackPanel>
</StackPanel>
<Button Grid.Row="1" x:Name="btnFindCoordinate" Content="Find data" Tap="btnFindCoordinate_Tap"/>
</Grid>
如前所述,我们希望在 Nokia Maps 控件中显示一个地点。在本文中,我将不详细介绍此控件,我们只关注将输入到 TextBox 控件的吸引力。首先,我们删除之前的 XAML 代码,并用以下代码替换它。
<!--ContentPanel - inserire ulteriore contenuto qui-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Insert a location" Margin="0,20,0,0"/>
<TextBox x:Name="tbxCity" Width="300"/>
</StackPanel>
<StackPanel>
<Controls:Map x:Name="mapLocation" Height="442" Width="480"/>
</StackPanel>
</StackPanel>
<Button Grid.Row="1" x:Name="btnFindCoordinate" Content="Find data" Tap="btnFindCoordinate_Tap"/>
</Grid>
</Grid>
查看代码,您会注意到我们有一个新控件。
<Controls:Map x:Name="mapLocation" Height="442" Width="480"/>
这是我们之前提到的 Nokia Maps 控件。有两种方法可以将控件放在屏幕上,一种是从工具箱中拖动并将其放置在堆栈面板中,这样会自动导入必要的命名空间,我们将在 MainPage.xaml 文件的顶部找到它。
xmlns:Controls="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
如果您决定手动编写,则必须记住在 Nokia Maps 控件上方引入命名空间。完成此操作后,如果一切都正确编写,我们将看到如下所示的屏幕。
从图片中可以看到,我们首先与 Nokia Maps 控件进行了比较。现在转到代码隐藏部分,我们修改按钮点击事件中的代码,调用一个名为 GetPosition() 的方法。
private void btnFindCoordinate_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
GetPosition();
}
现在是地址到坐标转换所需的代码。
public void GetPosition()
{
var latitude = 0d;
var longitude = 0d;
var locator = new Geolocator();
var geocodequery = new GeocodeQuery();
if (!locator.LocationStatus.Equals(PositionStatus.Disabled))
{
geocodequery.GeoCoordinate = new GeoCoordinate(0, 0);
geocodequery.SearchTerm = tbxCity.Text;
geocodequery.QueryAsync();
geocodequery.QueryCompleted += (sender, args) =>
{
if (!args.Result.Equals(null))
{
var result = args.Result.FirstOrDefault();
latitude = result.GeoCoordinate.Latitude;
longitude = result.GeoCoordinate.Longitude;
mapLocation.SetView(result.BoundingBox, Microsoft.Phone.Maps.Controls.MapAnimationKind.Parabolic);
}
};
}
else
{
MessageBox.Show("Service Geolocation not enabled!", AppResources.ApplicationTitle, MessageBoxButton.OK);
return;
}
}
分析代码。关于 Geolocator 类,与上一篇文章的示例相比,一切都没有改变,一切都保持不变。这段新代码的第一部分,我们声明了一个新的 GeocodeQuery 类型对象。
var geocodequery = new GeocodeQuery();
剩余的代码部分。
if (!locator.LocationStatus.Equals(PositionStatus.Disabled))
{
geocodequery.GeoCoordinate = new GeoCoordinate(0, 0);
geocodequery.SearchTerm = tbxCity.Text;
geocodequery.QueryAsync();
geocodequery.QueryCompleted += (sender, args) =>
{
if (!args.Result.Equals(null))
{
var result = args.Result.FirstOrDefault();
latitude = result.GeoCoordinate.Latitude;
longitude = result.GeoCoordinate.Longitude;
mapLocation.SetView(result.BoundingBox, Microsoft.Phone.Maps.Controls.MapAnimationKind.Parabolic);
}
};
}
通过传递虚拟值来增强 geo-coordinates 属性。如前所述,这作为起点,并且因为它在搜索位置阶段不会引发异常,因此调用 QueryAsync() 方法。最后,我们处理 QueryCompleted 事件,该事件在查询执行和完成后执行,将所有数据还原到 I
mapLocation.Center = new GeoCoordinate(latitude, longitude);
mapLocation.SetView(result.BoundingBox, Microsoft.Phone.Maps.Controls.MapAnimationKind.Parabolic);
在第一种情况下,我们有一个名为 Center 的属性。我们需要将一个 GeoCoordinate 类型的对象以及 QueryCompleted 事件执行后返回的纬度和经度值传递给此属性。
在第二种情况下,我们有一个名为 SetView() 的方法。这正是一种方法,与 Center 属性一样,能够将输入的点居中显示在地图上。此方法通过 BoundingBox 属性增强,该属性与 Center 属性一样,在 QueryCompleted 事件在 I
- 无
- Linear
- 抛物线
现在我们有了代码和 GUI 代码隐藏部分,是时候运行应用程序了,但在开始调试之前,您需要激活所需的功能。在解决方案资源管理器中,展开 Properties 文件夹,然后双击 WMAppManifest.xaml 文件,转到功能部分,如果尚未激活,则激活 ID_CAP_MAP 和 ID_CAP_LOCATION 功能,如下图所示。
完成此操作后,我们终于可以调试了。按 F5 键,启动应用程序,它最初将显示如图片所示。在本例中,我使用了 Nokia Lumia 820 进行测试。
现在我们输入一个城市名称,例如都灵(Turin)或您想要的任何名称。点击“查找数据”按钮,如果一切顺利,Nokia Maps 控件将开始搜索,您将在地图上看到该城镇的中心。
结论
在这第三篇文章中,我们看到了如何使用 GeocodeQuery 类在 Nokia Maps 控件中显示一个位置。同样,在这篇文章中,我们仅限于显示,但您可以使用 Nokia Maps 和地图控件做更多的事情。从下一篇文章开始,我们将开始探索并了解您可以做的一切,敬请关注,不断开发,不断开发。