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

如何在 Silverlight 应用程序中添加地图和 GIS

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2009 年 7 月 17 日

CPOL

12分钟阅读

viewsIcon

116543

ESRI 开发了一个 API,允许您使用 ESRI 的 ArcGIS Online 和 Bing Maps for Enterprise 提供的在线服务来嵌入地图和添加 GIS 功能。本文将演示如何使用 ESRI 的 ArcGIS API for Microsoft Silverlight/WPF。

引言

在专为 Web 设计的地理信息系统 (GIS) 和地图领域,用户对应用程序体验的要求越来越高。此外,这些基于 Web 的 GIS 应用程序的需求已超越了支持单一浏览器技术或平台。如果您现在正在构建一个 Web 应用程序,您需要的技术不仅要能提供更具吸引力的用户体验,还要有工具能让您将这种体验快速交付给多种浏览器和平台。ESRI 开发了一个 API,用于在 Microsoft Silverlight 平台上使用地图和 GIS 组件,名为 ArcGIS API for Microsoft Silverlight/WPF

其主要目的是简化为桌面和 Web 应用程序创建具有丰富 GIS 功能的地图的过程。

该 API 使您能够集成来自 ESRI 的 ArcGIS Server、ArcGIS Online 和 Bing Maps for Enterprise 的服务。API 提供的组件可以显示支持多种地图投影、动态和缓存(切片)地图服务的地图。它还允许在地图上绘制图形(例如,多点、折线、多边形、符号、属性)。例如,图形资源可用于保存用户绘制的多边形或显示满足用户定义查询的要素。通常,GIS Web 应用程序需要包含超越简单地图显示和交互的地理空间功能。针对这类功能需求,API 提供了一组任务类来执行常见的 GIS 任务。这些类使您可以轻松编写特定于应用程序的代码,以从 ArcGIS Server 服务中提取信息并将其呈现给用户。例如,一家电器维修公司可以使用地理处理任务生成行驶时间多边形,以估算服务调用的总时长。该 API 包括以下任务:

  • 查询 (Query) - 从地图服务中获取满足属性查询的要素。
  • 识别 (Identify) - 从地图服务中获取与某个位置相交的要素。
  • 查找 (Find) - 从地图服务中获取属性中包含特定值的要素。
  • 地址定位器 (Address locator) - 获取某个地址的位置(地理编码)或某个位置的地址(反向地理编码)。
  • 网络分析 (Network Analysis) - 计算路径并显示图形结果和方向。

  • 几何 (Geometry) - 执行几何运算,如缓冲、投影、计算面积和长度以及简化。
  • 地理处理 (Geoprocessing) - 通过执行已发布为地理处理服务的地理处理模型,进行复杂的 GIS 分析。

在我们直接深入探讨如何向 Silverlight 应用程序添加地图和 GIS 功能之前,了解 GIS 是什么及其重要性会很有帮助。GIS 让我们能够以多种方式查看、理解、质询、解释和可视化数据,从而以地图、地球、报告和图表的形式揭示关系、模式和趋势。GIS 通过以一种易于理解和分享的方式审视您的数据,帮助您回答问题和解决问题。

GIS 可以从三个方面来看待:

数据库视图:GIS 是一种独特的世界数据库——一个地理数据库 (geodatabase)。一种理解 GIS 的方式是将其视为一个空间数据库,其中包含的数据集用通用的 GIS 数据模型——要素、栅格、属性、拓扑、网络等来表示地理信息。

地图视图:GIS 是一组智能地图和其他视图,用于显示地球表面的要素和要素关系。可以构建基础地理信息的地图,并将其用作“数据库的窗口”,以支持信息的查询、分析和编辑。

模型视图:GIS 是一组信息转换工具,可以从现有数据集中派生出新的地理数据集。这些地理处理功能从现有数据集中获取信息,应用分析功能,并将结果写入新的派生数据集。地理处理涉及将一系列操作串联起来的能力,以便用户可以通过组合一个有序的操作序列来执行空间分析和自动化数据处理。

现在我们了解了 GIS 是什么,下一步就是使用 ESRI 开发的工具来添加此功能。

工具

要学习此示例,您需要以下内容:

ArcGIS API for Microsoft Silverlight/WPF 可免费用于非商业用途。若要在外部将其用于商业目的,您必须通过 ArcGIS Online 购买 ArcGIS Web Mapping APIs 的年度订阅。

入门

下面的示例展示了如何创建一个地图控件并添加一个地理处理任务,以 1、2 和 3 分钟的增量在地图上显示行驶时间多边形。此应用程序包含两个来自 ArcGIS Online 的 ArcGIS Server 切片(缓存)地图服务图层:街道地图和影像。它还包含一个自定义的启动范围,用于定义应用程序启动时的初始地图范围,以及一个导航工具、一个进度条和一个滑块控件,用于在街道地图和影像图层之间切换显示。以下步骤假设您熟悉 XAML 和 C#,已经 下载了 ArcGIS API for Microsoft Silverlight/WPF 程序集和 Silverlight 工具包,在 Visual Studio 中创建了一个 Silverlight 应用程序,并且正在应用程序主页面(例如 Page.xaml)的 XAML 视图中工作。

从 Silverlight Toolkit 中添加对 System.Window.Controls.Theming.BureauBlue.dll 的引用,并如下声明命名空间。此主题将用于滑块控件。要使用 ESRI 程序集,请在您的应用程序中添加对 ESRI.ArcGIS.Client.dll 的引用,并添加一个引用 ESRI.ArcGIS.Client 命名空间的 XML 命名空间。命名空间声明应如下所示。要显示任务的结果,您需要指定一个输出接口。对于显示结果要素的几何形状,您将使用一个 GraphicsLayer 和三个 SimpleFillSymbols 作为输出。然后,您将在 GraphicsLayer 上指定 MapTips 以显示结果的属性。MapTips 将使用 DictionaryConverter 类来启用与任务结果属性的绑定。在 ESRI.ArcGIS.Client 程序集中,为地图的 ESRI.ArcGIS.Client.ValueConverters 和 ESRI.ArcGIS.Client.Symbols 命名空间各添加一个 XML 命名空间。为了使用 ESRI 的导航工具,您需要引用 ESRI.ArcGIS.Client.Toolkit.dll 并声明一个命名空间。按如下方式创建网格行定义。

<UserControl x:Class="SilverlightApp.DriveTimes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:theme=
"clr-namespace:System.Windows.Controls.Theming;assembly=System.Windows.Controls.Theming.BureauBlue" 
xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
xmlns:esriConverters="clr-namespace:ESRI.ArcGIS.Client.ValueConverters;assembly=ESRI.ArcGIS.Client"
xmlns:esriToolkit="clr-namespace:ESRI.ArcGIS.Client.Toolkit;assembly=ESRI.ArcGIS.Client.Toolkit">
  <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="200"/>
  </Grid.RowDefinitions>

将 PictureMarkerSymbol、三个 SimpleFillSymbols 和一个 DictionaryConverter 声明为根 Grid 元素的资源。使用“x:Name”属性为每个资源指定一个唯一的名称,如下所示。您稍后将使用这些资源。PictureMarkerSymbol 将用于显示在地图上点击的位置,以查找行驶时间区域。DictionaryConverter 允许您指定绑定到特定的字典键。SimpleFillSymbols 将用于在地图上显示地理处理任务的输出。

<!—GEOPROCESSING TASK OUTPUT RESOURCES-->
          <Grid.Resources>
            <esriSymbols:PictureMarkerSymbol x:Name="DefaultMarkerSymbol"
                OffsetX="8" OffsetY="8" Source="blackcar.png" />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol1"
                Fill="#77FF9999" BorderBrush="#FFFF9999" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol2" Fill="#77FFFF99"
                BorderBrush="#FFFFFF99" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol3" Fill="#779999FF"
                BorderBrush="#FF9999FF" BorderThickness="2"  />
            <esriConverters:DictionaryConverter x:Name="MyDictionaryConverter" />
        </Grid.Resources>

将 Map 控件元素插入到页面中的一个容器元素中。在此示例中,容器是 Grid。使用 ESRI.ArcGIS.Client 命名空间标识符“esri”来定义包含 Map 控件的命名空间。使用“x:Name”属性为 Map 控件指定一个唯一的名称,如下所示。为地图定义一个启动范围以显示当前区域。使用属性语法定义地图的 Extent 属性。该属性值是一组由逗号分隔的四个数字,指定了最小 x、最小 y、最大 x 和最大 y 值。您还需要为 MouseClick 事件指定一个处理程序,以处理在地图上点击以启动行驶时间多边形的地理处理任务。您稍后将实现此处理程序。将两个 ArcGIS Server 切片地图服务图层添加到地图中。地图包含一个由 Layers 属性引用的图层集合。ArcGISTileMapServiceLayer 元素将使您能够引用由 ArcGIS Online 托管的 ArcGIS Server 缓存地图服务。定义指向地图服务端点的 Url,并为每个图层包含一个唯一的 id。

<!-- MAP-->
<esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White" Progress="MyMap_Progress"
    Extent="-122.5009,37.741,-           122.3721,37.8089"
    MouseClick="MyMap_MouseClick" >
    <esri:Map.Layers>
        <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
        Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
        <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
        Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />

在 Map 控件元素中声明一个 GraphicsLayer,并将其 ID 分配为“MyGraphicsLayer”。您将在应用程序的 .NET 代码中使用此 ID 来获取对该图层的引用。注意,GraphicsLayer 指定在 MapServerLayer 下方,以便它们在运行时绘制在 MapServiceLayer 之上。在 GraphicsLayer 元素内,指定一个 MapTip 来显示结果的非地理数据。在 MapTip 元素内,指定 MapTip 内容的背景。您可以使用一个 StackPanel 和一个 Border 嵌套在一个 Grid 中,如下所示。通过这种方式配置容器元素,MapTip 将自动调整大小以适应其内容。添加一个垂直方向且边距等于 5 的 StackPanel。在 StackPanel 内部,添加一个 TextBlock 来指定一个数据绑定表达式,以绑定到图形要素的 Info 属性。为此,请使用您上面声明的 DictionaryConverter。在 MapTip 元素内,DataContext 是当前要素的 Attibutes 属性。此属性是一个字典,其中键是字段名,值是该字段的要素属性值。由于 DictionaryConverter 启用了与字典内键的绑定,并且 MapTip 元素内的 DataContext 是一个字典,因此可以在 MapTip 元素内使用 DictionaryConverter 来指定对字段名的数据绑定。添加另一个 TextBlock 来绑定图形要素的 LatLon 属性。您将在页面的代码隐藏中明确地将这些属性添加到地理处理结果中。

<!-- MAP-->
  <esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White" 
    Progress="MyMap_Progress" Extent="-122.5009,37.741,-122.3721,37.8089"
      MouseClick="MyMap_MouseClick" >
        <esri:Map.Layers>
          <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
           Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
            <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
            Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />
            <esri:GraphicsLayer ID="MyGraphicsLayer">
              <esri:GraphicsLayer.MapTip>
               <Grid Background="LightYellow">
                 <StackPanel Orientation="Vertical" Margin="5">
                   <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
                      ConverterParameter=Info, Mode=OneWay}" HorizontalAlignment="Left" />
                   <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
                      ConverterParameter=LatLon, Mode=OneWay}" HorizontalAlignment="Left" />
                 </StackPanel>
                 <Border BorderBrush="Black" BorderThickness="1" />
               </Grid>
              </esri:GraphicsLayer.MapTip>
            </esri:GraphicsLayer>
          </esri:Map.Layers>
        </esri:Map>

使用 Silverlight 和 ArcGIS API for Microsoft Silverlight/WPF 的一个优点是,您可以添加一些简单的控件来增强应用程序的外观。例如,在下面的简短代码行中,我们添加了一个滑块控件和一个导航工具,用于放大/缩小、向北、东、南、西平移。此外,还有一些执行行驶时间地理处理任务的说明性文本和一个显示地图可用性的进度条。

<!-- ESRI NAVAGATION -->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Row="2" >
            <esriToolkit:Navigation x:Name="MyNavigation" Margin="5"/>
        </StackPanel>
<!-- SAMPLE TEXT-->
        <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,15,15,0" >
            <Rectangle Fill="#22000000" RadiusX="10" RadiusY="10" Margin="0,4,0,0" />
            <Rectangle Fill="#775C90B2" Stroke="LightSeaGreen"  RadiusX="10"
                RadiusY="10" Margin="0,0,0,5" />
            <Rectangle Fill="#FFFFFFFF" Stroke="ForestGreen" RadiusX="5" RadiusY="5"
                Margin="10,10,10,15" />
            <TextBlock x:Name="InformationText" 
                Text="Click on map to set location. Drive time areas of 1, 2,
                and 3 minutes will be displayed"
                Width="150" Margin="30,20,30,25" HorizontalAlignment="Left"
                TextWrapping="Wrap" />
        </Grid>
        <!--SLIDER-->
        <theme:BureauBlueTheme HorizontalAlignment="Right" VerticalAlignment="Top" 
            Background="Transparent" >
            <Slider Orientation="Horizontal"  Margin="10,10,10,10" Width="200"
                Minimum="0" Maximum="100" SmallChange="1" LargeChange="5"
                    Value="0" ValueChanged="Slider_ValueChanged"/>
            </theme:BureauBlueTheme>
        <!--PROGRESS BAR-->
        <Grid HorizontalAlignment="Center" x:Name="progressGrid"
            VerticalAlignment="Bottom"  Grid.Row="2"  Width="200"
            Height="20" Margin="5,5,5,5">
            <ProgressBar x:Name="MyProgressBar" Minimum="50" Maximum="100"/>
            <TextBlock x:Name="ProgressValueTextBlock" Text="100%"
                HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </Grid>

下面是 XAML 部分的完整代码。在接下来的步骤中,您将在 C# 中执行地理处理任务。

<UserControl x:Class="SilverlightApp.DriveTimes"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:theme="clr-namespace:System.Windows.Controls.Theming;
       assembly=System.Windows.Controls.Theming.BureauBlue"     
   xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
    xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;
      assembly=ESRI.ArcGIS.Client"
    xmlns:esriConverters="clr-namespace:ESRI.ArcGIS.Client.ValueConverters;
      assembly=ESRI.ArcGIS.Client"
    xmlns:esriToolkit="clr-namespace:ESRI.ArcGIS.Client.Toolkit;
      assembly=ESRI.ArcGIS.Client.Toolkit">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="200"/>
        </Grid.RowDefinitions>
        <!-- GEOPROCESSING TASK OUTPUT RESOURCES-->
        <Grid.Resources>
            <esriSymbols:PictureMarkerSymbol x:Name="DefaultMarkerSymbol" OffsetX="8"
              OffsetY="8" Source="blackcar.png" />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol1" Fill="#77FF9999"
              BorderBrush="#FFFF9999" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol2" Fill="#77FFFF99"
              BorderBrush="#FFFFFF99" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol3" Fill="#779999FF"
              BorderBrush="#FF9999FF" BorderThickness="2"  />
            <esriConverters:DictionaryConverter x:Name="MyDictionaryConverter" />
        </Grid.Resources>
        <!-- MAP-->
        <esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White"
            Progress="MyMap_Progress" Extent="-122.5009,37.741,-122.3721,37.8089"
            MouseClick="MyMap_MouseClick" >
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
                  Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
                <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
                 Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />
                <esri:GraphicsLayer ID="MyGraphicsLayer">
                    <esri:GraphicsLayer.MapTip>
                        <Grid Background="LightYellow">
                            <StackPanel Orientation="Vertical" Margin="5">
                                <TextBlock Text="{Binding Converter={
                                  StaticResource MyDictionaryConverter},
                                  ConverterParameter=Info, Mode=OneWay}"
                                  HorizontalAlignment="Left" />
                                <TextBlock Text="{Binding Converter={
                                  StaticResource MyDictionaryConverter},
                                  ConverterParameter=LatLon, Mode=OneWay}"
                                  HorizontalAlignment="Left" />
                            </StackPanel>
                            <Border BorderBrush="Black" BorderThickness="1" />
                        </Grid>
                    </esri:GraphicsLayer.MapTip>
                </esri:GraphicsLayer>
            </esri:Map.Layers>
        </esri:Map>
                <!-- ESRI NAVAGATION -->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Row="2" >
            <esriToolkit:Navigation x:Name="MyNavigation" Margin="5"/>
        </StackPanel>
    <!-- SAMPLE TEXT-->
        <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,15,15,0" >
            <Rectangle Fill="#22000000" RadiusX="10" RadiusY="10" Margin="0,4,0,0" />
            <Rectangle Fill="#775C90B2" Stroke="LightSeaGreen"  RadiusX="10"
               RadiusY="10" Margin="0,0,0,5" />
            <Rectangle Fill="#FFFFFFFF" Stroke="ForestGreen" RadiusX="5" RadiusY="5"
               Margin="10,10,10,15" />
            <TextBlock x:Name="InformationText"
               Text="Click on map to set location. Drive time areas of 1, 2,
               and 3 minutes will be displayed"
                Width="150" Margin="30,20,30,25" HorizontalAlignment="Left"
                TextWrapping="Wrap" />
        </Grid>
        <!--SLIDER-->
        <theme:BureauBlueTheme HorizontalAlignment="Right" VerticalAlignment="Top"
            Background="Transparent" >
            <Slider Orientation="Horizontal"  Margin="10,10,10,10" Width="200"
                Minimum="0" Maximum="100" SmallChange="1" LargeChange="5"
                    Value="0" ValueChanged="Slider_ValueChanged"/>
            </theme:BureauBlueTheme>
        <!--PROGRESS BAR-->
        <Grid HorizontalAlignment="Center" x:Name="progressGrid"
            VerticalAlignment="Bottom"  Grid.Row="2"  Width="200" Height="20"
            Margin="5,5,5,5">
            <ProgressBar x:Name="MyProgressBar" Minimum="50" Maximum="100"/>
            <TextBlock x:Name="ProgressValueTextBlock" Text="100%"
               HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </Grid>
    </Grid>
</UserControl>

执行任务

在应用程序的 XAML 中,您将 MyMap_MouseClick 方法声明为 Map 的 MouseClick 事件的处理程序。现在,您将在页面的代码隐藏中实现此处理程序。完成后,该处理程序将在点击的位置显示一个图标,实例化任务并配置其输入参数,然后执行地理处理任务。任务在代码隐藏中声明和初始化,因为任务本身不定义任何用户界面,而是封装了执行逻辑的片段。

声明 MyMap_MouseClick 方法,检索默认显示图标的 GraphicsLayer,并清除其中任何先前绘制的符号。实例化一个新的 Graphic,将其几何形状设置为地图上点击的点,并将其符号设置为引用默认图标的 PictureMarkerSymbol 资源。

  private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
            GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
            graphicsLayer.ClearGraphics();

            Graphic graphic = new Graphic()
            {
                Symbol = DefaultMarkerSymbol,
                Geometry = e.MapPoint,
            };

指定一个 Info 属性,这将允许通过您之前指定的 XAML 将值绑定到 MapTip。在一个名为 LatLon 的属性中添加 Graphic 结果的坐标。最后将该图形添加到 GraphicsLayer。

      graphic.Attributes.Add("Info", "Start location");
            string latlon = String.Format("{0}, {1}", e.MapPoint.X, e.MapPoint.Y);
            graphic.Attributes.Add("LatLon", latlon);
            graphic.SetZIndex(1);
            graphicsLayer.Graphics.Add(graphic);

要初始化一个地理处理任务,只需声明一个 geoprocessor 对象,使用 new 关键字实例化它,并将地理处理服务的 REST 端点的 URL 传递给构造函数。为任务的 ExecuteCompleted 事件指定一个处理程序,该处理程序将在地理处理器任务执行完毕时被调用。同时为任务的 Failed 事件指定一个处理程序,如果执行任务时出现问题,该处理程序将被触发。

//Initialize geoprocessing task
            Geoprocessor geoprocessorTask = new Geoprocessor(
                "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
                "Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons");
            geoprocessorTask.ExecuteCompleted += GeoprocessorTask_ExecuteCompleted;
            geoprocessorTask.Failed += GeoprocessorTask_Failed;

地理处理任务的执行方法接受一个 GPParameter 对象列表作为输入。所有的地理处理参数类(例如 GPFeatureRecordSetLayer, GPDouble, GPRecordSet 等)都派生自这个类。CreateDriveTimePolygons 服务有两个输入参数——Input_Location,类型为 GPFeatureRecordSetLayer,和 Drive_Times,类型为 GPString。有两套用于执行和处理地理处理任务结果的成员;同步和异步。本例将使用同步地理处理服务。当使用同步执行的服务时,您使用 ExecuteAsync 方法来启动操作。初始化参数和 ExecuteAsync 方法的代码如下:

//Add parameters to inputs and data types
            List<GPParameter> parameters = new Listlt;GPParameter>();
            parameters.Add(new GPFeatureRecordSetLayer("Input_Location", e.MapPoint));
            parameters.Add(new GPString("Drive_Times", "1 2 3"));
 
            geoprocessorTask.ExecuteAsync(parameters);
        }

为地理处理器任务的 ExecuteCompleted 事件声明一个处理程序。当任务完成时,将调用此处理程序。获取对结果 GraphicsLayer 的引用。事件处理程序会遍历结果要素,将每个要素添加到 GraphicsLayer 中。传递给处理程序的结果中的每个 GPParameter 都被假定为一个 GPFeatureRecordSetLayer 对象,因为这是此任务列出的输出类型。如果任务执行失败,将显示一个 MessageBox 来显示错误。下面最后两个方法实现了进度条和滑块控件的逻辑。

//Execute the geoprocessing task and draw results when find is complete
        private void GeoprocessorTask_ExecuteCompleted(object sender,
            ESRI.ArcGIS.Client.Tasks.GPExecuteCompleteEventArgs args)
        {
            GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
 
            foreach (GPParameter parameter in args.Results.OutParameters)
            {
                if (parameter is GPFeatureRecordSetLayer)
                {
                    GPFeatureRecordSetLayer gpLayer = parameter as GPFeatureRecordSetLayer;
 
                    List<FillSymbol> bufferSymbols = new List<FillSymbol>(
                    new FillSymbol[] { FillSymbol1, FillSymbol2, FillSymbol3 });
 
                    int count = 0;
                    foreach (Graphic graphic in gpLayer.FeatureSet.Features)
                    {
                        graphic.Symbol = bufferSymbols[count];
                        graphic.Attributes.Add("Info",
                            String.Format("{0} minute buffer ", 3 - count));
                        graphicsLayer.Graphics.Add(graphic);
                        count++;
                    }
                }
            }
        }
    //Notify user if task fails to execute
        private void GeoprocessorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Geoprocessing service failed: " + e.Error);
        }
     //Progess bar visibilty
        private void MyMap_Progress(object sender,
            ESRI.ArcGIS.Client.ProgressEventArgs args)
        {
            if (args.Progress < 100)
            {
                progressGrid.Visibility = Visibility.Visible;
                MyProgressBar.Value = args.Progress;
                ProgressValueTextBlock.Text = string.Format("{0}%", args.Progress);
            }
            else
            {
                progressGrid.Visibility = Visibility.Collapsed;
 
            }
        }
//Display layers in slider
        private void Slider_ValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            MyMap.Layers["ImageryLayer"].Opacity = e.NewValue / 100d;
            MyMap.Layers["StreetMapLayer"].Opacity = 1d - (e.NewValue / 100d);
        }
    }
}

下面是实现此示例执行逻辑的完整 C# 代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Tasks;

namespace SilverlightApp
{
    public partial class DriveTimes : UserControl
    {
        public DriveTimes()
        {
            InitializeComponent();
            MyNavigation.Map = MyMap;
        }


        //Find and mark the location of area when map is clicked
        private void MyMap_MouseClick(object sender,
            ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
            GraphicsLayer graphicsLayer = 
                MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
            graphicsLayer.ClearGraphics();

            Graphic graphic = new Graphic()
            {
                Symbol = DefaultMarkerSymbol,
                Geometry = e.MapPoint,
            };
            graphic.Attributes.Add("Info", "Start location");
            string latlon = String.Format("{0}, {1}", e.MapPoint.X, e.MapPoint.Y);
            graphic.Attributes.Add("LatLon", latlon);
            graphic.SetZIndex(1);
            graphicsLayer.Graphics.Add(graphic);

            //Initialize geoprocessing task
            Geoprocessor geoprocessorTask = new Geoprocessor(
                "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
                "Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons");
            geoprocessorTask.ExecuteCompleted += GeoprocessorTask_ExecuteCompleted;
            geoprocessorTask.Failed += GeoprocessorTask_Failed;

            //Add parameters to inputs and data types
            List<GPParameter> parameters = new List<GPParameter>();
            parameters.Add(new GPFeatureRecordSetLayer("Input_Location", e.MapPoint));
            parameters.Add(new GPString("Drive_Times", "1 2 3"));

            geoprocessorTask.ExecuteAsync(parameters);
        }
        //Draw results when find is complete
        private void GeoprocessorTask_ExecuteCompleted(object sender,
            ESRI.ArcGIS.Client.Tasks.GPExecuteCompleteEventArgs args)
        {
            GraphicsLayer graphicsLayer = 
                MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;

            foreach (GPParameter parameter in args.Results.OutParameters)
            {
                if (parameter is GPFeatureRecordSetLayer)
                {
                    GPFeatureRecordSetLayer gpLayer = parameter as GPFeatureRecordSetLayer;

                    List<FillSymbol> bufferSymbols = new List<FillSymbol>(
                    new FillSymbol[] { FillSymbol1, FillSymbol2, FillSymbol3 });

                    int count = 0;
                    foreach (Graphic graphic in gpLayer.FeatureSet.Features)
                    {
                        graphic.Symbol = bufferSymbols[count];
                        graphic.Attributes.Add("Info", 
                            String.Format("{0} minute buffer ", 3 - count));
                        graphicsLayer.Graphics.Add(graphic);
                        count++;
                    }
                }
            }
        }
        //Notify user if task fails to execute
        private void GeoprocessorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Geoprocessing service failed: " + e.Error);
        }
//Progess bar visibilty
        private void MyMap_Progress(object sender,
            ESRI.ArcGIS.Client.ProgressEventArgs args)
        {
            if (args.Progress < 100)
            {
                progressGrid.Visibility = Visibility.Visible;
                MyProgressBar.Value = args.Progress;
                ProgressValueTextBlock.Text = string.Format("{0}%", args.Progress);
            }
            else
            {
                progressGrid.Visibility = Visibility.Collapsed;

            }
        }
        //Display layers
        private void Slider_ValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            MyMap.Layers["ImageryLayer"].Opacity = e.NewValue / 100d;
            MyMap.Layers["StreetMapLayer"].Opacity = 1d - (e.NewValue / 100d);
        }
    }
}

借助本文提供的示例以及 ArcGIS API for Microsoft Silverlight/WPF 的灵活性,可以简单快捷地为您的 Silverlight 应用程序添加地图和 GIS 的强大功能。

想了解更多?

有关 ArcGIS API for Microsoft Silverlight/WPF 的交互式示例,请下载该 API 并访问 ESRI 的 ArcGIS Server 资源中心。在那里您将看到实时示例、文档和代码,以帮助您熟悉使用该 API 创建 Silverlight 应用程序。

关于作者

ESRI 自 1969 年以来,ESRI 一直在赋予全球客户以地理方式思考和规划的能力。作为 GIS 市场的领导者,ESRI 软件被全球超过 300,000 个组织使用,其中包括美国 200 个最大城市中的每一个、大多数国家政府、超过三分之二的财富 500 强公司以及 7,000 多所学院和大学。ESRI 的应用程序运行在超过一百万台台式机和数千台 Web 和企业服务器上,为世界地图绘制和空间分析提供了支柱。ESRI 是唯一一家为桌面、移动、服务器和互联网平台提供完整技术解决方案的供应商。

© . All rights reserved.