在用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