65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Phone 8 中的 GeocodeQuery 类。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.31/5 (4投票s)

2014 年 10 月 14 日

CPOL

8分钟阅读

viewsIcon

17011

downloadIcon

175

正如前一篇文章所述,地理定位是移动设备及其他设备中最常用的功能之一,通过它可以检索我们所在位置的信息,应用程序也可以利用它来获取其他信息,例如餐厅

引言

正如上一篇文章所述,地理定位是移动设备及其他设备中最常用的功能之一,通过它可以检索我们所在位置的信息,应用程序也可以利用它来获取其他信息,例如餐厅、酒店、名胜古迹以及许多其他场景。我们讨论了 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 类型的对象中。它正好是查询找到的所有结果,封装在一个集合中,因为结果也可能不止一个。要查找信息,我们需要引用 Result 属性。除此之外,我们还有
 

  • 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 类型的集合中。与上一篇文章的其他更改是这两行控制 Nokia Maps 的代码,两者都导致相同的结果。换句话说,搜索 TextBox 控件中输入的兴趣点。

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 类型集合中执行后返回,它代表了地图的一部分,包括纬度和经度,然后可以显示在 Nokia Maps 控件中,因此是 Center 属性的替代方案。SetView() 方法,除了 BoundingBox 属性,如果我们愿意,还可以定义另一个主题;它是一个 MapAnimationKind 枚举值,换句话说,是地图中搜索阶段的一种动画。我们有三个选择

  • Linear
  • 抛物线

现在我们有了代码和 GUI 代码隐藏部分,是时候运行应用程序了,但在开始调试之前,您需要激活所需的功能。在解决方案资源管理器中,展开 Properties 文件夹,然后双击 WMAppManifest.xaml 文件,转到功能部分,如果尚未激活,则激活 ID_CAP_MAP 和 ID_CAP_LOCATION 功能,如下图所示。

完成此操作后,我们终于可以调试了。按 F5 键,启动应用程序,它最初将显示如图片所示。在本例中,我使用了 Nokia Lumia 820 进行测试。

现在我们输入一个城市名称,例如都灵(Turin)或您想要的任何名称。点击“查找数据”按钮,如果一切顺利,Nokia Maps 控件将开始搜索,您将在地图上看到该城镇的中心。

 

结论

在这第三篇文章中,我们看到了如何使用 GeocodeQuery 类在 Nokia Maps 控件中显示一个位置。同样,在这篇文章中,我们仅限于显示,但您可以使用 Nokia Maps 和地图控件做更多的事情。从下一篇文章开始,我们将开始探索并了解您可以做的一切,敬请关注,不断开发,不断开发。

© . All rights reserved.