Silverlight+WCF+ArcObjects获取地图服务图层列表的实现

很久没有写博客了,最近一直忙考试,只是被悲催的数学物理方程真的把我给伤着了.....

忙完了考试,又开始了导师的项目,然而发现项目的很多东西,用原始的ArcGIS Api for Silverlight根本无法实现。于是开始接触强大的ArcObject。虽然之前接触过一些ArcGIS Engine,但还是觉得学的云里雾里的,现在都忘得差不多了,于是又一次的被AO给伤了。

本文算是自己初学AO的一点总结吧,在此和大家分享,不对之处,恳请指教。

一、Silverlight调用AO需要什么?

  • 安装ArcOjects for .net Framework
  • 需要借助WCF或者WebService
  • 在Web项目中添加ArcGIS引用

关于AO的基本知识,本人初学,在此就不卖弄了。可以查看官方的帮助文档,前提是你需要一定的英语知识。

ArcObject官方在线文档:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html

关于WCF和WebService,本人觉得用法差不多,但是WCF要更强大一些,所以建议使用WCF。至于什么是WCF或者WebService可以参考微软的官方文档:

WCF官方文档及示例:

http://msdn.microsoft.com/en-us/library/dd456779.aspx

二、实现过程

我们这实现的功能很简单,就是获得某一地图服务(MapServer)下的所有图层。例如本文的发布的地图服务如下:

那么我们可以知道这里又是个图层(Layers):

下面我们就通过调用AO的方式获取这些图层。

1.新建Silverlight项目

选中Enable WCF RIA Service

2.在Web项目中添加ArcGIS相关的引用,如下图所示:

3.在Web项目中添加Silverlight-enabled WCF Service

选择Silverlight-enabled WCF Service,并设置服务名称,点击Add

此时Web部分的基本工作已经完成,接下来看看WCF服务器端如何实现。

 4.WCF端实现的代码

首先我们需要连接到GIS服务,例如之前说的MapService,然后才能获取该服务的所有图层,连接到GIS服务的大致过程如下图所示:

关于连接GIS服务器的详细说明,可参考ESRI中国社区diligentpig的这篇文章:

http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=42676

以及官网的指导说明:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Connecting_to_a_GIS_server/000100000200000000/

(1):WCF服务器端的连接代码:

首先添加如下引用:

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System.Text;
using ESRI.ArcGIS.Location;

 

并定义如下变量:

 //用来存储GIS服务所有图层的名称
        public string[] LayerName = null;
        //获得主机的SOM对象
        public ESRI.ArcGIS.Server.IServerObjectManager pSOM = null;
        //获取GIS服务的Context
        public ESRI.ArcGIS.Server.IServerContext pServerContext = null;
        //服务器连接
        ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsconnection = null;
        //身份识别
        ESRI.ArcGIS.ADF.Identity identity = null;
        //GIS服务
        ESRI.ArcGIS.Carto.IMapServer2 pMapServer=null;
        //GIS服务的对象
        ESRI.ArcGIS.Carto.IMapServerObjects2 pMapServerObject = null;
        //GIS服务对象对应的地图,包含服务的所有图层
        ESRI.ArcGIS.Carto.IMap pMap = null;

 

然后再WCF的构造函数中实例化:

 //设置用户名,密码及域名
             identity = new ESRI.ArcGIS.ADF.Identity("ArcGISWebServices", "quzijing", "qzj");
            //设置服务地址
            agsconnection = new
                ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection("localhost", identity);
            agsconnection.Connect();
            pSOM = agsconnection.ServerObjectManager;
            //指定相应GIS服务的地址,以及GIS服务的类型
            pServerContext = pSOM.CreateServerContext("NetworkAnalystServiceFolder/RiverMap", "MapServer");
            //创建GIS服务对象及Map
            pMapServer = pServerContext.ServerObject as ESRI.ArcGIS.Carto.IMapServer2;
            pMapServerObject = pMapServer as ESRI.ArcGIS.Carto.IMapServerObjects2;
            pMap = pMapServerObject.get_Map(pMapServer.DefaultMapName);

 

这里需要说明的是:

a.identify的设置。和我们的ArcGIS Server Manager的UserName(用户名),Domain(域名),Password(密码)一致。

b.设置ArcGIS Server服务器地址:一般我们使用localhost即可,也可使用ip地址,当部署应用程序的时候建议使用IP地址。

c.指定GIS服务地址及服务类型:

GIS服务地址是相对于我们ArcGIS Server服务器根目录来说的,假设我们已有的GIS服务如下图所示:

那么如果我们想连接ChinaMap对应的MapServer时,使用的地址则直接是:ChinaMap,相应的代码为:

pServerContext = pSOM.CreateServerContext("ChinaMap", "MapServer");

而如果是要获取RiverMap对应的MapServer时,那么需要指定其相对于GIS服务的路径,即:NetworkAnalystServiceFolder/RiverMap,示例代码则为:

 pServerContext = pSOM.CreateServerContext("NetworkAnalystServiceFolder/RiverMap", "MapServer");

同时还需要注意的问题是第二个参数中的GIS服务类型必须一致。

(2).获取图层名称。

上面我们已经获得了指定服务的Map,通过该Map我们即可获得Map中包含的所有图层,示例代码如下:

 if (pMap.LayerCount > 0)
            {
                LayerName = new string[pMap.LayerCount];
                for (int i = 0; i < pMap.LayerCount; i++)
                {
                    ILayer layer = pMap.Layer[i];
                    LayerName[i] = string.Format("Map Layer {0}:{1}", i, layer.Name);
                }
            }

此外,我们个还可以获得指定的图层以及其中的要素,示例代码:

            IFeatureClass pFC = (pMap.get_Layer(1) as ESRI.ArcGIS.Carto.IFeatureLayer).FeatureClass;
            IFeatureCursor pPolyLineCursor = pFC.Search(null, false);
            IFeature pPolyFeature = pPolyLineCursor.NextFeature();

(3).定义WCF实现服务的契约

该契约方法返回制定GIS服务中所有的图层名称,即返回上面的LayerName字符数组,示例代码如下:

       [OperationContract]
        public string []GetLayerString()
        {
            if(LayerName==null)
            {
                LayerName = new string[1];
                LayerName[0] = "错误:没有获得图层";
            }
            return LayerName;
        }

以上过程我们便完成了服务器端的工作,接下来我们看看客户端的实现。

5.客户端的实现

首先添加WCF服务引用

此时我们的项目文件结构如下所示:

接下来实现客户端的功能,客户端的实现很简单,我们这里就只是获得制定GIS服务所有的图层名称,我们定义一个Button和一个ListBox

 <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="83,23,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
        <ListBox Margin="12,61,172,0" Name="listBox1" VerticalAlignment="Top" HorizontalAlignment="Left" />
  

后台代码:

 AOServiceReference.ArcGIS_AOServiceClient client = new ArcGIS_AOServiceClient();
        public MainPage()
        {
            InitializeComponent();
            client.GetLayerStringCompleted += new EventHandler<GetLayerStringCompletedEventArgs>(client_GetLayerStringCompleted);
        }

        void client_GetLayerStringCompleted(object sender, GetLayerStringCompletedEventArgs e)
        {
            //将WCF结果绑定到ListBox
            listBox1.ItemsSource = e.Result;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            client.GetLayerStringAsync();
        }

最后的效果:

点击Button,获得图层列表

 

 (版权所有,转载请标明出处)



 

posted @ 2012-12-15 11:32  Mr|Right  阅读(2501)  评论(1编辑  收藏  举报