在用SilverlightAPI开发的过程当中,不管是从客户端提交到服务器端的数 据,仍是从服务器端返回客户端的数据,都要表如今浏览器中,具体的来讲是Map控件里。但根据各自类型的不一样,好比数据源,地图服务的类型,是否缓存等, 决定了它们将处于某个图层里,前面讲过的GraphicsLayer就是一种图层。清楚地认识这些图层类型,对于处理于服务器与客户端之间的地图数据来讲 是很重要的。
全部的图层都是从Layer类型继承而来的,能够参考下载的API中的对象模型图。
Layer
|--TiledMapServiceLayer
| |--ArcGISTiledMapServiceLayer
|--DynamicLayer
| |--DynamicMapServiceLayer
| |--ArcGISDynamicMapServiceLayer
| |--ArcGISImageServiceLayer
| |--GPResultImageLayer
|--GraphicsLayer
| |--FeatureLayer
|--ElementLayer
下面就按顺序认识一下这些图层吧,也包括Silverlight API中独有的FeatureLayer。
一、Layer:
继承自Silverlight中的DependencyObject,并实现了INotifyPropertyChanged接口,是Silverlight API中其余图层的基类。能够把它当作麦子,再好吃的凉皮,泡馍都是由它作出来的;
二、TiledMapServiceLayer:
继承自Layer,是全部使用了缓存的地图服务的基类。经过它能够在程序中加入通过缓存的,来自不一样数据源的地图服务。好比ArcGIS Server的地图服务,Google Map的地图,Virtual Earth的地图等;
三、ArcGISTiledMapServiceLayer:
继承自TiledMapServiceLayer。像上面说的同样,这个图层扩展了TiledMapServiceLayer,因而支持由 ArcGISServer 9.3版本发布的通过缓存的地图服务;又好比ArcGIS Server9.2版本发布的缓存地图服务不支持REST方式链接,若是要在93的客户端API中使用的话,就能够经过 TiledMapServiceLayer扩展一个好比ArcGISTiledMapServiceLayer92,来支持92Server发布的缓存地 图服务;
四、DynamicLayer:
继承自Layer,是动态地图服务的基类;
五、DynamicMapServiceLayer:
继承自DynamicLayer,对应于TiledMapServiceLayer,要使用未通过缓存的动态地图服务,就得经过扩展这个图层来实现;
六、ArcGISDynamicMapServiceLayer:
继承自DynamicMapServiceLayer,针对ArcGIS Server9.3版本发布的动态地图服务。同理,若是要在客户端API中使用其余动态地图服务,好比OGC的WMS服务,则也须要像这个图层同样,扩展 上面的DynamicMapServiceLayer来实现;
七、ArcGISImageServiceLayer:
继承自DynamicMapServiceLayer,针对ArcGIS Server 9.3版本发布的ImageService,由于影像服务也属于动态的地图服务。在客户端API中,能够经过 ArcGISImageServiceLayer的一些属性,方便经过浏览器来展现服务器端的影像数据,好比经过BandIds属性,能够快速调整影像数 据显示波段的组合(RGB通道),提供不一样结果供用户查看。
点击这里,查看一个实例;
八、GPResultImageLayer:
继承自DynamicMapServiceLayer,针对Geoprocessing服务所产生的结果。能够请求服务器端的GP服务将结果动态生成一张图片,将此图片做为GPResultImageLayer图层直接添加到Map控件中;
九、GraphicsLayer:
继承自Layer,是图形数据集中展示的地方,在第四讲中已经详细讨论过了;
十、FeatureLayer:
继承自GraphicsLayer,这也是Silverlight API中的亮点之一,经过它能够完成一个比较炫的功能:
整个过程在xaml中就能够实现,只须要在Map的Layers中插入如下代码便可:
- <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
- <esri:FeatureLayer ID="featurelayer"
- Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0"
- Where="POP1990 > 75000" ClusterFeatures="True" FlareBackground="#99FF0000" FlareForeground="White" MaximumFlareCount="9"
- FeatureSymbol="{StaticResource markersymbol}">
- <esri:FeatureLayer.OutFields>
- <sys:String>CITY_NAME</sys:String>
- <sys:String>POP1990</sys:String>
- </esri:FeatureLayer.OutFields>
- <esri:FeatureLayer.MapTip>
- <Grid Background="LightYellow">
- <StackPanel Margin="5">
- <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
- ConverterParameter=CITY_NAME, Mode=OneWay}" FontWeight="Bold" />
- <StackPanel Orientation="Horizontal">
- <TextBlock Text="Population (1990): " />
- <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
- ConverterParameter=POP1990, Mode=OneWay}" />
- </StackPanel>
- </StackPanel>
- <Border BorderBrush="Black" BorderThickness="1" />
- </Grid>
- </esri:FeatureLayer.MapTip>
- </esri:FeatureLayer>
复制代码
可 以看出这个FeatureLayer实际上是将一个Query查询封装到了一个GraphicsLayer中。经过url指定查询的图层,where指定查 询条件(也能够输入geometry指定查询的图形),最关键的是ClusterFeatures="True",当一个范围内feature过多时,就 将他们“聚合”在一块儿,以一个更大的符号表示出来,进一步放大时才将它们单独显示出来,若是聚合的目标不超过MaximumFlareCount设置的数 目,那么就会出现那个flare动画。在MapTip(继承自GraphicsLayer)里面进行了简单的设置,一个背景为黄色的Grid里显示两行文 字,用一个DictionaryConverter类将返回的Graphic.Attributes集合中的两个字段转换成String类型显示出来。顺 便提一下,FeatureLayer也能够用于线或面层的查询,但若是继续使用ClusterFeatures的话就没什么意义了。虽然 FeatureLayer封装的比较死,只能有此一种效果,但它提供给咱们一种思路,能够结合SilverlightRIA的特性,充分发挥本身的想象力 作出更炫的效果来;可是,对于须要展示海量(成百上千个)点数据的图层来讲,ClusterFeatures是一个很是有用的特性,毕竟将这么多点同时呈 现出来性能仍是有问题的。若是不使用ClusterFeatures,看起来应该是这样的:
不用FeatureLayer行吗?
说到FeatureLayer,还有两个Renderer不得不提一下:UniqueValueRenderer和 ClassBreakerRenderer。它们都是依托FeatureLayer的,用于单值专题图的渲染。具体的用法都比较简单,能够查看API中的 Concepts。但Samples中的ThematicRendering例子并无采用这两种Renderer,而是人为地为每一个Graphic设置 了不一样的Symbol。目前看来虽然这两个Renderer有点鸡肋,但毕竟是如今3种客户端API中提供的惟一现成的Renderer,能够猜测也许下 个版本的SilverlightAPI中会有更加成熟的专题图Renderer直接供咱们使用;
十一、ElementLayer:
继承自Layer,它能够用来专门呈现Silverlight中原生的FrameworkElement,好比视频,音频等。虽然在 FillSymbol的Fill属性中也能利用Brush类来展示一段视频,但毕竟有些“小气”,在ElementLayer中能够大大方方的放置 Silverlight元素。你可能会问,在Map控件以外,Grid等布局元素中不是也能放置Silverlight的东西吗,为何要放在 ElementLayer里呢?其实有个问题常常困扰GIS开发人员,就是想让一些非地理数据元素随着地图范围的变化(放大,缩小,平移)而变化,而无须 本身在Extent变化后从新计算客户端坐标,手工改变这些元素的位置。瞧,ElementLayer正解决了这个问题。
目前Beta版的API中暂时有这么多图层类型,之后也许会继续增长。但万变不离其宗,无非就是从那几个基类中派生出来的。因此,下一节咱们就经过 一个实例来看看如何扩展基类的MapServiceLayer,来达到使用非ArcGIS Server数据源的目的。程序员
原文地址:http://bbs.esrichina-bj.cn/ESRI/thread-45537-1-1.htmlweb
经过上一节学习,能够看出在Silverlight API中不只能够轻松使用ArcGIS Server9.3发布的地图服务,也能够经过继承相应的图层,引入其余的数据源,好比ArcGIS Server9.2发布的地图服务,WMS服务,或者其余免费的数据。本节就经过一个实例,来看看如何将Google Map做为底图数据。
Google Map是通过缓存的数据,因此须要继承的是TiledMapServiceLayer。那么在扩展这个图层的时候须要作哪些工做呢?首先就要明白
地图缓存的原理。能够看出咱们继承的这个图层,须要收集到如下几个信息:
一、Tiling Scheme Origin;
二、切图的范围,也就是FullExtent;
三、SpatialReference;
四、TileInfo,包括切图的大小,级数,以及每级的Resolution;
五、最后就是重写GetTileUrl方法。
这是为何呢?能够想象,当地图控件的范围改变时,可以获取到当前范围的信息,那么只要把左上角和右下角之间的Tile所有按顺序显示出来就好了。 由前面的文章能够看出,当图层获取了一、二、三、4四个信息后,图层彻底能够自动计算出所需的Tile,最后根据GetTileUrl方法取回这些 Tile显示出来便可。
那么对于Google Map的前4个参数,如何取得呢?记得在Catalog中作缓存时,有一个LoadTiling Scheme from Google Map吗?按照这个TilingScheme将一个地图服务作缓存,而后查看它的conf.xml和ServiceDirectory,便彻底能够取得这 几个参数了。另外关于如何获取Google Map的缓存,网上已经有很是多方法,这里就再也不讨论了。
代码以下:
- public class GoogleMap:TiledMapServiceLayer
- {
- public override void Initialize()
- {
- this.FullExtent = new
- ESRI.ArcGIS.Geometry.Envelope(-20037508.342787,-20037508.342787,20037508.342787,20037508.342787);//(-180,
- -85.0511287798066,180, 85.0511287798066)
- {
- SpatialReference = new ESRI.ArcGIS.Geometry.SpatialReference(102113);
- };
- this.SpatialReference = new ESRI.ArcGIS.Geometry.SpatialReference(102113);
- //this.InitialExtent = this.FullExtent;
- this.TileInfo = new TileInfo()
- {
- Height = 256,
- Width = 256,
- Origin = new ESRI.ArcGIS.Geometry.MapPoint(-20037508.342787,
- 20037508.342787)//Origin = new ESRI.ArcGIS.Geometry.MapPoint(-180, 90)
- {
- SpatialReference = new ESRI.ArcGIS.Geometry.SpatialReference(102113)
- },
- Lods = new Lod[20]
- };
- double resolution = 156543.033928;
- for (int i = 0; i < TileInfo.Lods.Length; i++)
- {
- TileInfo.Lods[i] = new Lod() { Resolution = resolution };
- resolution /= 2;
- }
- base.Initialize();
- }
- public override string GetTileUrl(int level, int row, int col)
- {
- //google maps map
- //string baseUrl = "http://mt0.google.com/mt/v=ap.92&hl=zh-CN&x=";
- //string url = baseUrl + col.ToString() + "&y=" + row.ToString() + "&z=" + level.ToString() + "&s=";
- //return url;
-
- ////google maps satallite
- string baseUrl = "http://khm2.google.com/kh/v=38&hl=zh-CN&x=";
- string url = baseUrl + col.ToString() + "&y=" + row.ToString() + "&z=" + level.ToString() + "&s=";
- return url;
- }
- }
复制代码
须要注意一点,Google Map采用的是WGS 1984 Web Mercator投影,这个投影的wkid在RESTAPI中查不到,但在ServiceDirecotry中能够找到,是102113。另外,重写 DynamicMapServiceLayer也是基本相同的。
以后也能够按照这个Tiling Scheme对本身的服务做缓存,本身的数据和Google Map即可以叠加在一块儿了。可是这样子使用GoogleMap的数据不只担忧会被封IP,并且更重要的是版权问题,毕竟不像JS API(有ArcGIS JavaScript Extension forthe Google Maps API )或者Flex API(有Google Map API forFlex)。别忘了MS有本身的Virtual Earth,下一节中就来看看如何在咱们的程序中名正言顺的使用VE的数据吧。编程
原文地址:http://bbs.esrichina-bj.cn/ESRI/thread-45582-1-1.htmlwindows
SilverlightAPI中还包括了一个ESRI.ArcGIS.VirtualEarth.dll类库,让咱们能够方便的访问到老东家的 VirtualEarth服务。目前SilverlightAPI中提供的VirtualEarth服务有三种:Map,Geocode和 Routing,不过一看就知道后两种服务对于国内的数据来讲又无缘了。
直接看如何使用它的Map服务获取地图数据吧。同前,新建一个Silverlight工程,添加ESRI.ArcGIS.dll和ESRI.ArcGIS.VirtualEarth.dll的引用,引入xml命名空间,在xaml里面这样写:
- <esri:Map x:Name="Map1" Loaded="Map1_Loaded">
- <esri:Map.Layers>
- <esriVE:TileLayer ID="VELayer" LayerStyle="AerialWithLabels" ServerType="Staging"/>
- </esri:Map.Layers>
- </esri:Map>
复制代码
可 以看出,和添加其余图层基本是同样的。SIlverlightAPI中针对VE地图的图层类型是TileLayer,LayerStyle有三 种:Road,Aerial和AerialWithLabels,分别对应矢量图,影像图和带街道标注的影像图。ServerType就比较特殊了,有两 种:Staging和Production,分别对应访问VE服务的帐户类别,前者是免费的,后者是收费的。若是你此时运行程序的话,那是看不到地图的, 由于TileLayer还有个关键的token属性没有设置。
VE的服务那是至关安全,每次访问VE的服务,都要提供一个token(一个加密字符串)来进行身份验证,而这个token又是根据 TokenService自动生成的,要经过TokenService生成一个token,又须要一个合法的Microsoft Virtual Earth Platformdeveloper account……明白了这个过程,就来作咱们的工做吧。
首先,
去申请一个Microsoft Virtual Earth Platform developer account,固然以前你还得有一个Windows Live帐号。申请的这个帐号是Evaluation版的,因此决定了之后咱们只能使用Staging的服务,若是要把它变成Production版本,能够经过邮件联系微软,而后缴费;
以后到注册时所填的邮箱去激活申请的Microsoft Virtual Earth Platform developeraccount帐号,而后为其设置密码(必须是8-14为之间,包括大、小写字母,数字,且还要有非字母数字的字符,和windows server2008是同样的),咱们日常确定不会这样设置密码,为了以防万一,建议赶忙把设置好的密码记录下来,
没准哪天就忘了。如今就能够用这个帐户和密码来访问TokenService,经过它生成token,交给TileLayer的token属性。
为了安全目的考虑,token是不建议也不能直接在Silverlight程序中进行设置的。那么怎么办呢?这样办:一、经过装载 Silverlight的aspx页面的Page_Load方法,来申请咱们的token,并把它添加到Silverlight的初始参数中,二、而后当 Silverlight插件载入的时候,把token读出来,三、在Map_Loaded事件中,赋给TileLayer。
一、经过TokenService申请token:
在webapp中add webreference,url用
https://staging.common.virtualearth.net/find-30/common.asmx?wsdl,起个名字叫VirtualEarthService.TokenService。
- <script language="C#" runat="Server">
- private string VEAccountID = "你的ID(注意只是AccountID)";
- private string VEAccountPassword="你的密码";
-
- protected void Page_Load(object sender,EventArgs e)
- {
- _08_virtual_earth.Web.VirtualEarthService.TokenService.CommonService
- commenservice = new
- _08_virtual_earth.Web.VirtualEarthService.TokenService.CommonService();
-
- commenservice.Credentials = new System.Net.NetworkCredential(VEAccountID, VEAccountPassword);
- _08_virtual_earth.Web.VirtualEarthService.TokenService.TokenSpecification
- tokenSpec=new
- _08_virtual_earth.Web.VirtualEarthService.TokenService.TokenSpecification();
- tokenSpec.TokenValidityDurationMinutes=480;
- if (HttpContext.Current!=null && !HttpContext.Current.Request.IsLocal)
- {
- tokenSpec.ClientIPAddress=HttpContext.Current.Request.UserHostAddress;
- }
- else
- {
- tokenSpec.ClientIPAddress="127.0.0.1";
- }
-
- string token = "";
- token = commenservice.GetClientToken(tokenSpec);
- Xaml1.InitParameters = string.Format("token={0}", token);
- }
- </script>
复制代码
其中Xaml1是Silverlight插件的ID:<asp:Silverlight ID="Xaml1" runat="server"...
二、Silverlight插件载入时读出这个token。在App.xaml.cs中:
- private void Application_Startup(object sender, StartupEventArgs e)
- {
- VEtoken = e.InitParams["token"];
- this.RootVisual = new Page();
- }
复制代码
三、最后在加载地图控件后,交付token:
- private void Map1_Loaded(object sender, RoutedEventArgs e)
- {
- foreach (Layer layer in Map1.Layers)
- if (layer is TileLayer)
- (layer as TileLayer).Token = (Application.Current as App).VEtoken;
- }
复制代码
终于能看见VE的图了。固然,咱们的开发帐户是免费的,因此地图上有不少“Staging”麻点(每一个tile一个):
至此,ArcGIS API for Silverlight的开发入门已经讲完了,我和你们同样也是边学边写的,恰好这两天SIlverlightAPI又升级了第二个Beta版。其实 Silverlight和Flex同样,能使传统的WebGIS散发出全新的魅力,从而使咱们的程序在RIA的道路上大踏步前进,可以作出什么样的效果也 基本只受想象力的制约了。随着Silverlight3的推出,咱们也有理由相信Silverlight的明天会更好。api
原文地址:http://bbs.esrichina-bj.cn/ESRI/thread-45835-1-1.html