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
以及官网的指导说明:
(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,获得图层列表
(版权所有,转载请标明出处)