原創作者:<不詳>
一、前述
(原創作品網址:http://www.vscodes.com/article/3/2379.Html)
(以下針對於Windows操作系統.Net開發環境)
ArCGIS Server是ESRI公司最新推出的服務器端品,主要可以實現兩大功能:
1、強大的Web GIS系統的開發;
2、分布式GIS系統的開發;
ArcGIS Server其內核與ArcGIS Desktop和ArCGIS Engine一樣,都是ArcObjects庫。其所謂的Web GIS,其實無非就是用Web技術來封裝ArcObjects而已;而分布式的開發則是通過DCOM來實現的。
小弟前幾個月搞了一下ArcIMS,發覺開發起來確實痛苦啊,整天就是折騰Javascript+arcXML,郁悶死了,聽聞有ArcGIS Server這種好東西,稍稍了解一下,便向老板建議轉向ArCGIS Server,老板居然同意了。於是便開發學習了。網上四下裡找了一下,發現可用的資源非常少,只好自己琢磨。從零開始真不容易啊,這不,剛上手就碰到了兩個問題,好在都已經解決,現在寫下來,希望對和我一樣的新手有所幫助。
ArcGIS Server的安裝非常簡單,先安裝ArCGIS Server,然後安裝DotNet ADF,最後用ArcCatelog添加一個Server,然後再添加一個ServerObject,這樣就可以進行開發了。這裡的ServerObject與ArcIMS中的Service很像,其實應該是一個概念上的東西吧。添加一個ServerObject需要一個mxd或pmf文件,用來保存和管理需要發布的數據。
好了,現在可以開始開發了。
打開Visual Studio 2003,打開新建項目對話框,發現ESRI公司已經為我們准備好了一些ArCGIS Server Projects的模板,包括Map Viewer Web Application,Page Layout Web Applicaiton等等,我們就建一個Map VIEwer Web Application吧,選中它,輸入項目名稱,然後點擊“確定”按鈕,我們發現一個已經包含了基本數據浏覽和查詢功能的Web GIS程序已經建好了。
好,打開Default.ASPx文件,發現網頁包含一個Map組件,一個Toolbar組件,一個TOC組件,一個OverviewMap組件等等。看來與C/S開發模式下很像嘛,爽啊。其中Map組件和OvervIEwMap組件有兩個必填屬性:Host和ServerObject,就分別對應著我們在ArcCatelog中添加的的Server和ServerObject,輸入它。然後設置TOC組件和Toolbar組件的Buddy屬性,OK,大功告成!
運行!咦,發生錯誤,定睛一看,原來是訪問拒絕,這是怎麼回事呢?記得以前看到一篇文章,說在ASP.Net中使用COM組件,經常由於權限原因,產生訪問拒絕,而ArCGIS Server本身就是對ArcObjects這些COM組件的再封裝,看來就是這麼回事了。找出這篇文章來,原來要在Web.config中加入一行就可以了:
<identity impersonate="true" userName="Administrator" passWord="123456"/>
再運行,哇塞,酷斃了,一個漂亮的WebGIS展現在眼前。可以浏覽,查詢,圖層管理,鷹眼導航,還有指北針...
(後來發現頁面上還一個組件叫impersonation沒用上,看了一下它的屬性,只有一個identity,點擊它,你會發現...呵呵,原來這個組件就是用來干這個事的,暈,又浪費了我兩個小時的寶貴時間...)
一行代碼都不用寫,爽。可是又很失落,心裡沒有底,這個Web GIS究竟是怎樣實現的呢?
二、開發講解(一)
(原創作品網址:http://www.vscodes.com/article/3/2380.Html)
我們知道,.Net ADF提供的map組件、toc組件等都是標准的ASP.net組件。這些組件在運行時,會生成相應的Html代碼,將自己展現出來。一般還會通過VIEwState來保存狀態,並生成_doPostBack(Javascript)函數,在必要的時候,通過Javascript來調用該函數,將客戶端數據返回來服務器端,從而激發服務器的響應。總之,我們通過分析生成的Html頁面,應該可以大致窺見ASP.Net組件是怎麼運行的。
好,我們現在按F5運行首頁,然後在浏覽器中查看網頁的源代碼,趕快看下一吧:
1、首先會看到ID,MapIdClick,start等Javascript函數,這些函數是模板為我們生成的,在default.ASPx文件中定義的。ID函數中有兩行:
var iddiv = document.getElementById("MapDiv_Map1");
if (iddiv!=null) iddiv.onmousedown = MapIdClick;
可以看到,這幾個函數的作用是對地圖的Identify(點擊查詢)作出處理。
為什麼要放在這裡呢,為什麼單單只有點擊查詢的Javascript要在這裡定義呢,其它如放大、縮小、平移為什麼不在這裡處理?這是因為Toolbar組件對放大、縮小、平移等提供了默認的處理方式,而identify沒有,這樣可以更方便進行擴展。在後面的代碼中有一行<esri:Tool ToolTip="Identify" DefaultImage="Images/identify.gif" ClIEntToolAction="ID()" Name="Identify"...>,可以看到,這個調用是模板為我們生成的(並且這個調用是可以修改的)。待會我們在進一步分析中可以看到這一點。
2、再向下,是幾個隱藏域,其中包含__VIEWSTATE隱藏域,還有__doPostBack函數,這些是ASP.Net組件生成的,作用是向服務器提交數據,從而與服務器進行交互。
3、往下我們看到了一些引入JS腳本文件的代碼:
<script language="Javascript" src="/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/JavaScript/common.JS"></script>
<script language="Javascript" src="/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/JavaScript/map_functions.JS"></script>
<script language="Javascript" src="/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/JavaScript/overvIEw_functions.JS"></script>
<script language="Javascript" src="/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/JavaScript/toolbar_functions.JS"></script>
可以看到,共引入了四個JS腳本文件,這些文件的地址也比較奇怪,不是與當前網站在同一個虛擬目錄下,而是在http://localhost//aspnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/Javascript目錄下。在c:/inetpub/webroot/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/JavaScript/文件夾下可以找到這些文件。原來,為了重用的方便,在安裝ArCGIs Server時,安裝程序就已經建立了一個虛擬目錄,用於提供這些共享的資源。在這個文件夾上一級目錄中,還可以看到images和treeimages兩個子目錄,以及treevIEw.htc文件。
知道了這些Javascript文件的藏身之所,各位可以把這些Javascript文件逐個看一遍,可以發現其作用主要是與浏覽器進行交互。
4、再往下,是TOC組件的Html代碼,代碼片斷如下:
<tvns:treenode Expanded="False" Default ImageUrl="/ASPnet_clIEnt/esri_arCGIs_server_webcontrols/9_1/images/outscale.gif" CheckBox="False">
道路注記<tvns:treenode Expanded="True" ImageUrl="ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.ASPx_Toc1_0_1_0_0&NoCache=true"></tvns:treenode>
這一段代碼有一個特別之處就是ImageUrl="ESRI.Web.Controls.MIMEImage.aspx...",這個ESRI.Web.Controls.MIMEImage.ASPx是什麼東東,是一個網頁嗎?在機器裡找一下,發現根本就不存在這個網頁,那它又是何方神聖,竟然可以作為一個圖片的地址?我們先往下看看。
5、<div id=''OvervIEwMap1backdrop'' style = ''position: absolute; left: 16px; top: 400px; width:204px; height:124px;
Z-INDEX:104; border-color:LightSteelBlue; border-width:3px; border-style:Solid; overflow:hidden;''>
<table cellspacing=0 cellpadding=0 style = ''width:198px; height:118px; overflow:hidden;''><tr><td id=OVCell_OvervIEwMap1></td></tr></table>
</div>
是鷹眼導航圖的代碼。怎麼只有一個空的Div層和一個空的表格呢?唉,比較簡單,我懶得分析了,同志們自己去找吧~
6、再往下是Toolbar組件的代碼,沒什麼特別的:
<td nowrap width="29" height ="32" align=''Center''
id="Toolbar1ZoomIn"
onMouseDown="ToolbarMouseDown( ''Toolbar1'', ''ZoomIn'', ''Tool'', event);"
onMouseOver="ToolbarMouSEOver(''Toolbar1'', ''ZoomIn'');"
onMouseOut="ToolbarMouSEOut( ''Toolbar1'', ''ZoomIn'');"
><img id="Toolbar1ZoomInImage" alt="Zoom In" src="Images/zoominD.gif" align="absMiddle"></td>
7、再下面是生成地圖組件的代碼:
<script language="JavaScript" id="cs_dynamic_Map1">
Maps[mapCounter] = new MapCreation(''Map1'',0,mapCounter,0,0,502,378,''MapDiv_Map1'',''Black'',2);
mapURL[mapCounter] = "ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.ASPx-Map1&ct=5";
MakeMapDiv(mapCounter, ''Map1'',''ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.ASPx-Map1&ct=5'', ''MapCell_Map1'','''');
mapCounter++;
MapDragRectangle(''Map1'',''ZoomIn'', true);
</script>
又看到了MIMEImage這個東東!它究竟是什麼東東呢?
如果對ASP.Net不是很熟悉的話,要破解這個秘密可能確實比較困難。
在ASP.net中,所有的請求,都是通過httpHandler來進行處理的。那httphandler又是什麼東東呢?其實只要實現在IHttpHandler接口的類,都可以作為一個HttpHandler。在web.config或Machine.config文件中,可以定義哪些請求可以由哪個httphandler來處理。查看一下web.config文件,沒有這些聲明。那就看一下mapchine.config文件吧,這個文件在Windows\Microsoft.Net\Framework\v1.1.4322目錄下,用記事本打開它,查找ESRI.Web.Controls.MIMEImage.ASPx,好家伙,果然在這裡啊!
<httpHandlers>
<add verb="*" path="ESRI.Web.Controls.MIMEImage.ASPx" type="ESRI.ArcGIS.Server.WebControls.ImageHandler, ESRI.ArCGIS.Server.WebControls, Version=9.1.0.722, Culture=neutral, PublicKeyToken=8fc3cc631e44ad86"/>
原來ESRI.Web.Controls.MIMEImage.ASPx請求是能過ESRI.ArcGIS.Server.WebControls.ImageHandler來處理的。在Visual Studio中,使用對像浏覽器查看一下esri.arCGIs.server.webcontrols.dll文件,可以看到ImageHandler類,果然實現了IHttpHandler接口。呵呵,其實很簡單嘛,我們也完全可以自己寫一個類,來執行自定義的請求。
三、開發講解(二)
(原創作品網址:http://www.vscodes.com/article/3/2381.Html)
在(二)中我們分析了Html代碼,也就基本弄清了.Net adf怎樣封裝客戶端的交互,以及客戶端怎樣與服務器端進行交互。下面我們再看一看服務器端的開發方式是怎樣的,實際是就是進入了比較簡單的實戰。用其它工作開發Web GIS的朋友如果能夠了解一下AGS的實現,一定會有很的大啟發,你會在其中學到一些封裝客戶端、服務器端以及兩者交互的技巧,怎樣做到既封裝一些常用的功能,又不妨礙我們進行功能的擴充。
好了,廢話少說,開始我們新的體驗吧。
在(一)中我們已經說了,.Net adf提供了一系列的模板,這些模板又根據不同的需要,封裝了一些常用的功能。我們的開發一般是從這些模板開始的。如果我們對這些模板生成的程序已經很熟了,當然也可以不需要這些模板,但如果你是新手,請從模板開始,這樣可以避免走很多彎路。
首先,我們啟動Visual Studio 2003,新建一個項目,在新建對話框中,在“項目類型”中可以看到ArCGIS Server Projects這一項,選擇語言Visual C#,在右邊的模板列表中可以看到有七種模板可供選擇,每種模板可用於新建不同用途的應用,如下圖所示:
我們先新建一個Map VIEwer Web Application,也就是地圖浏覽程序。我們待會通過分析可以看到這個地圖浏覽程序是怎樣實現的,以及怎樣擴充自己的功能。
新建了一個Map VIEwer Web Application之後,界面如下圖所示。可以看到,.net為我們新建了一個ASP.Net web工程。工程包括三個頁面,default.aspx,errorpage.aspx和identify.aspx。其中,default.aspx是主界面,errorpage.aspx用於出錯信息的顯示,identify用於點擊查詢操作的結果的顯示。下面我們主要分析default.ASPx這個網頁。
這個網頁的的上部分是一個banner,不用管。下部分由七個ASP.Net組件構成。這七個組件分別是:
1、Map組件:地圖組件。有兩個關鍵屬性:Host和ServerObject,不用我說,也知道這是什麼意思。
2、Toc組件:圖層控件組件(table of contents)。有一個關鍵屬性BuddyControl,即與哪個Map組件相關聯。
3、Toolbar組件:工具條組件。有一個關鍵屬性BuddyControls,表示可以綁定多個Map組件或PageLayout組件。
4、OvervIEwMap組件:導航圖組件。有三個關鍵屬性Host,ServerObject和BuddyControl。
5、Impersonation組件:身份驗證組件。有一個關鍵屬性identity,用於設計怎麼登錄到服務器,擁有操作的權限。
6、NorthArrow組件:指北針
7、ScaleBar組件:比例尺組件,有一個關鍵屬性BuddyControl。BarFont屬性好像有Bug,怎麼設置也不起效,字體總是很小,不知為什麼,哪位朋友也幫俺一個忙,看看怎麼回事?
這七個組件中,顯然Map組件最為重要,因為它負責地圖顯示並與用戶交互。我們看一下Map組件有的事件,只有MapChanged的事件包含代碼,仔細看一下,是與視圖(地圖范圍)保存相關的代碼。那Map組件與用戶交互以及服務器端的處理代碼,如縮放地圖,在哪裡呢?
再看一看Toolbar組件,共包含七個按鈕,分別是放大,縮小,平移,全圖,上一視圖,下一視圖和點選。點開它的ToolbarItems屬性看一下,原來工具條按鈕的定義都在這裡面。
工具條按鈕有兩種類型:Tool和Command
Tool:工具按鈕。表示點擊後並不立即執行某項功能,而是需要用戶與地圖進行交互再執行。所以需要保存它的狀態。並且同時需要有相應的客戶端代碼(Javascript)和服務器端代碼。放大、縮小、平移和點選屬於這種類型。
Command:命令按鈕。立即執行某項操作,不需要有戶交互,所以不需要何存狀態。全圖、上一視圖、下一視圖屬於這種類型。
我們在ToolbarItems的定制界面中,選中identify,看一下它的屬性,包括五部份:
1、Appearance Images組:定義按鈕顯示的圖片。這些設置會轉化成Html代碼。
2、Appearance Text組:有兩個子項。Text表示在按鈕中顯示的文字,也就是說按鈕可以由圖片和文字兩部份組成。ToolTip,即鼠標放在按鈕上面時顯示的提示信息。
3、Client-side Action組:這組只有一個屬性,就是ClIEntToolAction,這裡就是與客戶端交互的Javascript代碼了。內容是ID()。我們打開defaut.ASPx,查看Html,可以看到ID函數的內容。這裡交互比較簡單的情況,交互比較復雜,如放大時需要拉框,怎麼封裝?原來,CIEnt-side Action實際上只是Javascript中onmousedown的執行函數,拉框所需的onmousemove和omnouseup去哪裡找?其實只是一個小技巧而已,在onmousedown中動態地給onmousemove和onmouseup賦值不就可以了嗎?事實上,.Net adf封裝zoomin等操作就是這要樣做的。
ClIEnt-side Action屬性有一個下拉選項,包含的是DragImage,DragRectangle,Point,Line,PolyLine,Polygon,Circle,Oval,none,Custom。不用解釋,相信大家也明白了,是Toolbar組件封裝了各種不同類型的客戶端操作。這些與客戶端交互的Javascript在哪裡呢?(二)中已經介紹了,這裡就省略啦。
4、General組。包括Disabled,Name,ShowLoading三個屬性。
5、Server-side Action組:有兩個屬性,ServerToolActionAssembly和ServerToolActionClass,用於定義服務器端要執行的功能。在.Net adf中,每個被封閉的服務端操作,都是由一個類來實現的,ServerToolActionAssembly表示這個類在哪個程序集中,ServerToolActionClass就是這個類的名稱。我們在ServerToolActionAssembly中選擇ESRI.ArcGIS.Server.WebControls,可以清楚的看到該程序集中定義了四個這種類:MapCenterAt,MapPan,MapZoomin,MapZoomout。事件上,我們也可以定義自己的處理類,只要實現ESRI.ArCGIS.Server.WebControls.Tools.IMapServerToolAction接口就可以了。
; 關於擴展:
1、客戶端交互:即ClIEnt-side Action組,adf封裝了DragImage,DragRectangle,Point,Line,PolyLine,Polygon,Circle,Oval這幾種操作,相信已經能夠應付我們絕大部份的應用了。如果還不行,別忘了最後還有一項custom,選中它,自己寫Javascript就可以了。記得是onmousedown的Javascript哦。在交互完畢後的代碼中,如果需要返回到服務器端的話,記得執行_doPostback函數。
2、服務器端功能實現:即Server-side Action組。Map組件針對客戶端封裝的每種行為,都提供了一個事件,表示客戶端交互完畢後,立即執行該事件中的代碼。這些事件有Oval,Line,Point,Polygon等。如果客戶端操作是自己寫的Javascript,並最後提交了操作到服務器的話,可以在Page_Load中處理你自己的操作。
上面介始的是Tool類型的工具條按鈕。至於Command類型的就簡單多了,我們可以選中FullExtent看一下,它的屬性少了ClIEnt-side Action組和Server-side Action組。它的實現代碼就直接到Toolbar組件的CommandClick事件中。自己去看吧。
其它組件就不介紹了。
說了這麼多,相信您對用.net adf開發Web GIS已經有一個大致的了解,也基本明白了.Net adf的封裝方式,您已經可以開始償試修改已有的功能,或者進行一些簡單的擴展了。下一節我就再介紹一下怎樣進行簡單的功能擴展。
四、開發講解(三)
(原創作品網址:http://www.vscodes.com/article/3/2382.Html)
這一節主要貼代碼算了,通過代碼看一下一些簡單功能的實現。偶快要放假了,靜不下心來寫了,寫得也不好。說不定貼代碼效果更好。
1、獲取所有圖層
ESRI.ArCGIS.Server.WebControls.WebMap webmap= Map1.CreateWebMap();
try
{
ESRI.ArCGIS.Carto.IMapDescription descr = webmap.MapDescription;
ddlLayers.Items.Clear();
int id;
for (int i=0;i<= descr.LayerDescriptions.Count-1;i++)
{
id = descr.LayerDescriptions.get_Element(i).ID;
ddlLayers.Items.Add(id.ToString() + "," + webmap.LayerNameFromID(id)); //ddlLayers是一個DropDownList控件
}
if (ddlLayers.Items.Count>0)
{
ddlLayers.SelectedIndex=0;
}
}
finally
{
webmap.Dispose();
}
2、通過圖層的ID獲取圖層對象
private IFeatureLayer GetFeatureLayer(int lyid)
{
WebMap webmap = Map1.CreateWebMap();
try
{
ILayer layer = (webmap.MapServer as IMapServerObjects).get_Layer(webmap.DataFrame,lyid);
if (layer==null)
return null;
else
{
return (layer as IFeatureLayer);
}
}
finally
{
webmap.Dispose();
}
}
3、新建一個多邊形
private void Map1_Polygon(object sender, ESRI.ArCGIS.Server.WebControls.PolygonEventArgs args)
{
if (args.ToolName == "newpolygon")
IFeatureLayer flayer = GetCurFeatureLayer(); //獲取當前活動圖層了函數,這裡就不貼了,就是調用GetFeatureLayer(int lyid)函數
if (flayer == null) return;
if (flayer.FeatureClass.ShapeType != ESRI.ArCGIS.Geometry.esriGeometryType.esriGeometryPolygon)
{
string sc;
sc = "<script language=Javascript>alert(''當前圖層何類型不對!'')</script>";
Page.RegisterClIEntScriptBlock("ShapeTypeError",sc);
return;
}
//生成多邊形
ESRI.ArCGIS.Server.IServerContext context;
ESRI.ArCGIS.Server.WebControls.WebMap webmap = Map1.CreateWebMap();
webmap.ManageLifetime(flayer);
context = webmap.ServerContext;
ESRI.ArcGIS.Geometry.IPolygon poly = context.CreateObject("esriGeometry.Polygon") as ESRI.ArCGIS.Geometry.IPolygon; //''new ag.PolygonClass();
webmap.ManageLifetime(poly);
ESRI.ArCGIS.Geometry.IPoint pt;
ESRI.ArcGIS.Geometry.IGeometryCollection ringcol = context.CreateObject("esriGeometry.Polygon") as ESRI.ArCGIS.Geometry.IGeometryCollection;// new PolygonClass();
webmap.ManageLifetime(ringcol);
ESRI.ArcGIS.Geometry.IPointCollection ptcol =context.CreateObject("esriGeometry.Ring") as ESRI.ArCGIS.Geometry.IPointCollection;// new RingClass();
webmap.ManageLifetime(ptcol);
object obj=Type.Missing;
for (int i=0;i<=args.Vectors.Length-1;i++)
{
pt = webmap.ToMapPoint(args.Vectors[i].X,args.Vectors[i].Y);
ptcol.AddPoint(pt,ref obj,ref obj);
}
ringcol.AddGeometry(ptcol as IGeometry,ref obj,ref obj);
poly = ringcol as IPolygon;
//將多邊形寫入到圖層中
ESRI.ArCGIS.Geodatabase.IFeature feature = flayer.FeatureClass.CreateFeature();
feature.Shape = poly as IGeometry;
feature.Store();
webmap.Refresh();
webmap.Dispose();
}
}
4、矩形選擇,獲得選擇集,並在地圖上顯示選中的對象。(這個功能花費了偶一天多的時間。)
private void Map1_DragRectangle(object sender, ESRI.ArCGIS.Server.WebControls.ToolEventArgs args)
{
string strTool = args.ToolName.ToLower();
if (strTool=="rectsel")
{
//取得當前層
if (ddlLayers.SelectedValue=="")
return;
IFeatureLayer flayer = GetCurFeatureLayer();
if (flayer == null) return;
//獲得選擇集
int t1=Environment.TickCount;
ESRI.ArCGIS.Server.WebControls.WebMap webmap = Map1.CreateWebMap();
ESRI.ArCGIS.Server.IServerContext ctx = webmap.ServerContext;
webmap.ManageLifetime(ctx);
ESRI.ArcGIS.Geodatabase.IWorkspace ws = (flayer.FeatureClass as ESRI.ArCGIS.Geodatabase.IDataset).Workspace;
ESRI.ArcGIS.Geometry.IEnvelope env = ctx.CreateObject("esriGeometry.Envelope") as ESRI.ArCGIS.Geometry.IEnvelope;
webmap.ManageLifetime(ws);
webmap.ManageLifetime(env);
IPoint pt = webmap.ToMapPoint(Convert.ToInt32(Request.Params.Get("maxx")),Convert.ToInt32(Request.Params.Get("maxy")));
env.XMax = pt.X;
env.YMin = pt.Y;
pt = webmap.ToMapPoint(Convert.ToInt32(Request.Params.Get("minx")),Convert.ToInt32(Request.Params.Get("miny")));
env.XMin= pt.X;
env.YMax = pt.Y;
ESRI.ArcGIS.Geodatabase.ISpatialFilter filter = ctx.CreateObject("esriGeodatabase.SpatialFilter") as ESRI.ArCGIS.Geodatabase.ISpatialFilter;
webmap.ManageLifetime(filter);
filter.SpatialRel = ESRI.ArCGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects;
filter.Geometry = env as ESRI.ArCGIS.Geometry.IGeometry;
filter.GeometryField = flayer.FeatureClass.ShapeFIEldName;
ESRI.ArcGIS.Geodatabase.ISelectionSet sset = flayer.FeatureClass.Select(filter,ESRI.ArcGIS.Geodatabase.esriSelectionType.esriSelectionTypeSnapshot,ESRI.ArCGIS.Geodatabase.esriSelectionOption.esriSelectionOptionNormal,ws);
int t2=Environment.TickCount;
int t3=t2-t1; //t3是查詢響應的時間,可以用來測試一下性能,呵呵
//顯示選擇集
int id;
ESRI.ArCGIS.Geodatabase.IEnumIDs ids;
ids = sset.IDs;
webmap.ManageLifetime(ids);
ids.Reset();
ESRI.ArcGIS.Geodatabase.IFIDSet fidset = ctx.CreateObject("esriGeodatabase.FIDSet") as ESRI.ArCGIS.Geodatabase.IFIDSet;
id = ids.Next();
while (id>=0)
{
fidset.Add(id);
id =ids.Next();
}
IMapDescription desc = webmap.MapDescription as IMapDescription;
webmap.ManageLifetime(desc);
ILayerDescription ldesc = desc.LayerDesc
riptions.get_Element(flyid);
webmap.ManageLifetime(ldesc);
ldesc.SelectionFeatures = fidset;
//將選擇信息保存在session中
Session["selection"] = sset;
Session["layerid"] = flyid;
webmap.Refresh();
webmap.Dispose();
}
}
5、刪除選中的對象
private void DeleteSel()
{
if (Session["layerid"]==null) return;
if (Session["selection"] == null) return;
int layerid = (int)Session["layerid"];
if (layerid == -1) return;
ESRI.ArcGIS.Geodatabase.ISelectionSet sset = Session["selection"] as ESRI.ArCGIS.Geodatabase.ISelectionSet;
if (sset == null) return;
WebMap webmap = Map1.CreateWebMap();
IFeatureLayer layer = GetFeatureLayer(layerid);
if (layer==null) return;
webmap.ManageLifetime(layer);
webmap.ManageLifetime(sset);
ESRI.ArCGIS.Geodatabase.IEnumIDs ids = sset.IDs;
webmap.ManageLifetime(ids);
ids.Reset();
int id;
id = ids.Next();
ESRI.ArCGIS.Geodatabase.IFeature feature;
ESRI.ArCGIS.Server.IServerContext ctx = webmap.ServerContext;
webmap.ManageLifetime(ctx);
//將selectionset轉化為featurecursor對象
ESRI.ArCGIS.Geodatabase.IFeatureCursor fcursor;
ESRI.ArCGIS.Geodatabase.ICursor cursor;
sset.Search(null,false,out cursor);
fcursor = cursor as ESRI.ArCGIS.Geodatabase.IFeatureCursor;
ESRI.ArcGIS.esriSystem.ISet pDeleteSet = ctx.CreateObject("esriSystem.Set") as ESRI.ArCGIS.esriSystem.Set;
webmap.ManageLifetime(pDeleteSet);
//設置ISet對象
feature = fcursor.NextFeature();
while (feature != null)
{
pDeleteSet.Add(feature);
feature = fcursor.NextFeature();
}
ESRI.ArCGIS.Geodatabase.IFeatureEdit fedit;
;pDeleteSet.Reset();
fedit = pDeleteSet.Next() as ESRI.ArCGIS.Geodatabase.IFeatureEdit;
while (fedit != null)
{
fedit.DeleteSet(pDeleteSet);
fedit = pDeleteSet.Next() as ESRI.ArCGIS.Geodatabase.IFeatureEdit;
}
Session.Remove("layerid");
Session.Remove("selection");
webmap.Refresh();
webmap.Dispose();
}