技术开发 频道

无处可逃!Silverlight实现BingMap定位

        【IT168专稿】在上篇Silverlight4应用Bing Maps构建程序 中,我们探讨了如何使用Bing Maps Silverlight控件并借助Bing提供的地理信息服务呈现针对指定代码的地图信息。在本篇中,我们将继续构建这个案例程序,使之支持浏览器外执行功能并将进一步细化这个实例,使之实现当鼠标移动到指定地理位置时显示相关提示信息。【提示】本文示例开发环境为:

  •   WINDDOWS XP Professional(SP3);
  •   .NET 4.0;
  •    VS2010+Microsoft Silverlight 4 Tools for Visual Studio 2010;
  •   Bing Maps Silverlight Control SDK。


    一、定位和标示地图上的机场

  现在,地球服务Geoservice已经启动并运行,地图也初步显示出来了。那么,接下来我们可以标记地图上的机场位置。

  首先,我们要创建一个MapLayer类型的私有变量imageLayer:

Private MapLayer imageLayer imageLayer;

   然后,我们在GetAirports()方法的开头处添加下面的代码:

imageLayer MapLayer = new MapLayer();
myMAP.Children.Add (imageLayer);

   第一行创建一个类MapLayer的实例。这个地图层类十分重要,可以创建于地图之上,并使用一些给定信息定制。在本例中,我们通过把它添加为地图控件myMAP的子控件的方式实现。

  接下来,我们来分析本示例中最为重要的调用Bing服务的代码:

private void Search(string id){
    
if (_geoservice == null) {
        _geoservice
= new geoService.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
        _geoservice.GeocodeCompleted
+= new EventHandler<geoService.GeocodeCompletedEventArgs>(_geoservice_GeocodeCompleted);
    }
    _geocodeRequest.Query
= id;
    _geoservice.GeocodeAsync(_geocodeRequest);

}

   上面是典型的以异步方式在Silverlight客户端调用一个外部WCF服务的代码。没有太多需要说明的。但注意在调用方法中传递了一个重要参数id。此参数正是要查询的飞机场的id标记。

  接下来,我们来看服务调用成功时的处理返回数据的相关代码:

void _geoservice_GeocodeCompleted(object sender, geoService.GeocodeCompletedEventArgs e)
  {
        
if (e.Result.ResponseSummary.StatusCode == geoService.ResponseStatusCode.Success && e.Result.Results[0].EntityType == "Airport")
    {
          Image img
= new Image();
          img.Source
= new BitmapImage(new Uri("Flag2_Green.png", UriKind.Relative));
          img.Width
= 20;
          img.Height
= 20;
          imageLayer.AddChild(img, e.Result.Results[
0].Locations[0]);
          var airport
= Airports.Where(p => p.Name == e.Result.Results[0].DisplayName).FirstOrDefault();
          airport.Location
= e.Result.Results[0].Locations[0];
    }
  }

 

   首先,我们需要核实返回的结果状态。如果成功的话(即结果的类型是Airport),我们将创建一个类型为Image的对象,改变了该对象的图像来源(一面绿色的小旗子)及大小属性,然后添加此图像到定制地图层的相应位置。接下来,我们根据服务返回的Airport实例数据,把它添加到前面定义的字典uiElements中。

  现在,我们已经在地图上标记好了飞机场的位置。我们的目的是,当选择下拉列表框中的飞机场名时应用程序会在地图中显示此位置对应的数据。为此,我们再回到文件MainPage.xaml中定位到ListBox控件lstbAirports处创建一个SelectionChanged事件处理器。

<ListBox x:Name="lstbAirports" Margin="10,0,0,0" SelectionChanged="lstbAirports_SelectionChanged">

   接下来创建上面的SelectionChanged事件处理器代码,如下所示:

private void lstbAirports_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {
        myMAP.SetView((lstbAirports.SelectedItem
as Airport).Location, 14);
  }

 
   在这里,我们仅是调用了地图控件的SetView方法以便把地图的当前焦点设置为你从列表中选择的飞机场所在位置。另外,传递给这个方法的第二个参数代表了要放大显示的倍数。

  现在,让我们来补充解释一个前面提到的称为uiElements的变量,其数据类型为Dictionary。这个结构能够把一幅图像映射到飞机场数据以方便后面返回飞机场状态数据时的处理。其初始化代码如下所示:

uiElements = new Dictionary<Airport,UIElement>();

 
  现在,再切换到事件处理器_geoservice_GeocodeCompleted中。请注意下面的代码:

if (!uiElements.ContainsKey(Airports.Where(p => p.Name == e.Result.Results[0].DisplayName).FirstOrDefault()))
      uiElements.Add(airport, img);

   在这段代码中,我们首先确定是否当前飞机场名称位于界面中的下拉列表中。如果不在,则把图像与飞机场数据添加到前面新创建的字典结构中(它们将用于后面要讨论的状态映射)。

0
相关文章