配电网WebGIS研究与开发[3]
作者:一点一滴的Beer http://beer.cnblogs.com/
第3章 配电网WebGIS基本功能实现
在上一章中,对基本的AJAX进行了一些介绍,但是Web GIS开发框架Web ADF提供的AJAX对上述基本的AJAX又进行了一层封装。ArcGIS Server9.3的Web ADF为开发人员提供了可以在AJAX环境中管理客户端与服务器之间传输的框架。这个框架称之为“callback results framework“,包括服务器端的一些类(CallbackResultCollection,CallbackResult)及控件(Web ADF controls)和客户端的JavaScript库(Web ADF JavaScript),如下图所示。
图3.1 Web ADF回调结构框架图示
服务器与客户端之间的响应是通过CallbackResult来实现的。事实上,一个CallbackResult是由服务器端的Web ADF control生成的、特定的、以JSON格式化的字符串。所有的Web ADF controls都具有CallbackResults属性,通过CallbackResultsCollection可以添加、删除这些CallbackResults,或者将其转换为字符串显示。当然,也可以自己定义一个CallbackResult,而不是由服务器控件生成,这将在后面的内容中介绍。服务器端将CallbackResult传到客户端之后,就交由客户端的Js函数ESRI.ADF.System.processCallbackResult()来实现客户端内容的刷新。总体上说来,callback result框架简化了开发人员的工作,以异步的方式实现了ADF以及非ADF控件内容的刷新。
按照需要刷新控件的不同,我们分Web ADF控件和非Web ADF控件的刷新两部分来介绍。
一、Web ADF控件的刷新
Web ADF为开发者提供了一系列的控件,比如常用的Map、Toc、Toolbar等。改变地图范围、图层是否可视、地图渲染等都需要刷新上述控件。之前提到每个ADF控件都具有CallbackResult属性,我们需要做的就是将需要刷新的ADF控件的CallbackResult复制到Map.CallbackResults,再返回给客户端的Web ADF Js函数processCallbackResult()处理。
例如,添加了一个新的图层,需要刷新Map以及Toc,我们就需要添加如下代码:
Toc1.Refresh();
Map1.CallbackResults.CopyFrom(Toc1.CallbackResults);
实际的过程如下图所示:
图3.2 Web ADF控件的刷新
在Web ADF控件之间管理callback result依赖于CallbackResultCollection类。它提供了一些方法,可以方便的添加、删除CallbackResult。最常用到的包括Add方法和CopyFrom方法。前者用于向CallbackResultCollection添加自定义的CallbackResult实例,后者用于复制某个CallbackResultCollection实例到另一个CallbackResultCollection实例。当然,你也可以用ToString方法将CallbackResult转换为字符串。更多关于CallbackResultCollection类的使用请参照ArcGIS Server的离线帮助,这里不一一赘述。
这里需要强调的是,并不是所有ADF控件的刷新都需要明确的在服务器调用刷新方法,这在Map控件上体现的尤为明显。比如,地图范围的改变或者地图比例的变化都会引起Map控件自动更新其callback result collection。其他情况,如更改地图的可见性或者添加删除某个地图资源都需要明确调用刷新方法。下面列出一些Web ADF控件之间的内联关系,在这些情况下,不需要明确调用刷新方法。
1.当工具栏控件绑定到地图控件,在工具栏上的任何操作都会自动将地图的callback result添加到工具栏的call back result collection。
2.当Toc控件绑定到地图控件,控制Toc里图层可见性的按钮也会实现自动刷新。
二、非Web ADF控件的刷新
页面中除了Map、TOC等ADF控件,一般还包含有很多非ADF控件,比如Button、Label、GridView等等。刷新这些控件的内容,可以完全脱离ArcGIS Server的CallbackResult,比如用UpdatePanel。如果你还想使用CallbackResult,当然也是可以的,但必须自己定制CallbackResult字符串。
CallbackResult类定义了一些静态方法可以方便开发者快速定制自己刷新客户端非Web ADF控件的内容。如表3.1所示。
表3.1 CallbackResult提供的方法
CallbackResult Static Method | Description |
---|---|
CreateSetContent | Set the outerHTML property of an html element. |
CreateSetInnerContent | Set the innerHTML property of an html element. |
CreateSetImageSource | Set the src property of an image element. |
CreateJavaScript | Execute JavaScript. on the client. |
CreateIncludeJavaScript | Include JavaScript. on the client |
CreateIncludeStyleSheet | Include a CSS style. sheet on the client |
服务器端定制的CallbackResult实例都会被客户端的Web ADF Javascript函数processCallbackResult()处理。processCallbackResult函数将包含以下代码来处理定制的CallbackResult内容:
[JavaScript]
if(action==='javascript') {
var method = function() {
try { eval(params[0]); }
. . .}
else if (action==="content") {
var o = $get(controlID);
if (o) { o.outerHTML=params[0]; }
. . .}
else if (action==="innercontent") {
var o2 = $get(controlID);
if (o2) { o2.innerHTML=params[0]; validResponse = true; }
. . .}
else if (action==="image")
{
var o3 = $get(controlID);
if (o3) { o3.src = params[0]; }
. . .}
else if (action=='include') {
var id = params[0];
var elm = (id?$get(id):null);
. . .
if(elm) { elm.parentNode.removeChild(elm); }
document.getElementsByTagName('head').item(0).appendChild(elm);
. . .}
最后要强调的是,无论使用哪种AJAX模式,回调技术(callback)还是部分页面刷新(partial postback,或称为ASP.NET AJAX),callback result的内容以及客户端处理callback result的函数都是一样的。
有了上述“callback results framework“的AJAX基础后,就可以对下面的功能的具体实现过程进行开发和研究了。
3.1 WebGIS电力设备参数查询
要求:在已经存在的WebGIS 基本模板上加入对电力设备图层的查询功能。对电力设备进行查询,查询方式包括两种:一种是利用工具条对地图中指定位置的设备进行查询,这是以地理位置作为查询依据;另外一种是用户输入相关字符然后对数据库进行查询,这是以设备的属性字段作为查询依据。
3.1.1 地图交互查询
要求:用户在客户端通过鼠标和地图控件进行“点选交互”,然后客户端显示出在鼠标所在地图位置被点选中的设备详细信息。
在服务器端(注:本文中提到的“服务器端”就是指建立C#编写的服务器端代码,同样“客户端”则指用HTML标记语言或者JavaScript编写客户端运行代码,虽然在进行开发的时候都是在本地PC上建立的,但是这样描述可以让各种源文件的职能分工更加明确)建立一个继承于ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl的控件MapIdentify,并让其隶属于名空间“WebMapApp”,然后此控件就拥有了回调函数和回调队列等等服务器和客户端端的ADF数据接口和函数接口供调用,开发人员可以通过编写服务器端和客户端代码来实现其相关的功能(主要功能和框架模板已经给出),在客户端只需要在页面文件前面加入对此名空间的引用声明即可使用此控件:
<%--自定义服务器控件-地图查询控件--%> <%@ Register Assembly="App_Code" Namespace="WebMapApp" TagPrefix="uc1" %> |
---|
图3.3 地图交互查询实现流程
1. 客户端鼠标交互产生坐标信息:
ESRI公司为了适应WebGIS的需要,除了提供了大量的服务器端控件和API外,还提供了资源丰富的客户端JavaScript库,这个库称为"Web ADF JavaScript Library "它是在ASP.NET AJAX JavaScript Library基础上创建的,提供了一套复杂的客户端框架,通过这套框架可以在脚本环境中与Web ADF控件或组件进行交互。这将意味着你可以使用javascript和Web ADF控件进行交互,比如浏览地图,添加graphics到地图上,创建map tips,不需要任何的服务器端代码。从另一个角度来说,Web ADF JavaScript Library为web adf开发人员提供了另外一个工具。Web ADF JavaScript 设计用来利用客户端的技术来增强Web ADF应用,以支持客户端/服务器端的同步以及纯客户端的交互,而不是代替服务器端编程独立使用的。这套library只要页面中有Web ADF控件便可使用,它不需要独立安装,嵌入在web adf控件中,不可更改。它在Web ADF之外不可使用,它主要用来配合arcgis server web adf进行开发使用的。
Web ADF JavaScript Library依赖于ASP.NET AJAX JavaScript Library,ASP.NET AJAX JavaScript Library提供了一个复杂的基础,在此基础上用来创建AJAX的解决方案(数据交换层次如图3.4)。它管理着客户端与远程服务,以及服务器端的控件的交互。它提供一种机制在客户端呈现Web控件以及客户端的事件处理。另外,它提供了跨浏览器的支持,所有的这些特性都在Web ADF JavaScript Library被使用了。下面是它们几者的关系图。关于Web ADF JavaScript Library的详细帮助可以在arcgis server的帮助中查到。
通过Web ADF JavaScript Library所提供的一些客户端API,我们可以直接在客户端对Web ADF控件进行一些操作,例如:设置地图控件呈现的范围,对地图中指定位置进行色彩着重显示,控制Web ADF服务器控件在客户端的外观和显隐,获取Web ADF服务器控件在客户端的一此状态信息并捕捉其客户端发生的事件等等。通过Web ADF JavaScript Library对Web ADF控件进行的一些操作是不需要经过服务器端的纯客户端操作,一般只是负责页面显示和数据收集等工作,涉及到数据更新时,还是需要和服务器端进行通讯获取新数据。
在进行地图交互查询时,查询的依据是设备在地图上的坐标值,这个坐标在用户使用鼠标和客户端地图控件进行交互时的事件产生,通过客户端Web ADF JavaScript Library中的接口函数很容易就能够提取到这个坐标并进行简单的字符编码:
……
var mappnt = new ESRI.ADF.Geometries.Point(geom.get_x(), geom.get_y());//提取坐标
……
var argument = "mode=identify&coords=" + geom.get_x() + ":" + geom.get_y();//编码 ……
this.doCallback(argument,this);//执行回调――向服务器端发送数据
……
客户端对地图坐标值进行编码后,然后再将编码的字符串通过异步的方式传递给服务器,然后再由服务器端来承接此数据,并进行相关操作。
图3.4 Web ADF控件数据交换层次图
2. 服务器端数据查询:
客户端向服务器端发起请求并将坐标数据传至服务器端,服务器端将对此请求作出响应,服务器端通过一个重载的函数GetCallbackResult来对客户端请求进行响应,通过Web ADF控件中的_callbackArg成员来承接客户端传送的数据。然后Web应用程序的运行地由客户端转向服务器了,下面就由服务器来处理回调请求了。
服务器端对收到的字符串进行解码并提取出坐标数值(具体解码过程已经在上一章运行了详细介绍了),然后调用Web ADF提供的API对地图数据库进行检索并得到满足要求的地图属性表,具体操作流程如下:
图3.5 地图图层查询流程
对如下图所示的地理数据源(以“分接箱”图层为例)进行检索,得到的是一个满足查询要求的数据集合:
图3.6 “分接箱”地理数据表
得到的查询结果中,数据表一般包括两类字段:图元几何字段和图元附加属性字段。如上图所示的数据表中,前面两个字段“FID”(图形要素编号),“Shape”(几何类型,比如此处是多点类型)就是和几何相关的字段,后面两个字段“NAME”(名称),“SBBH”(设备编号)则是作为附加属性对图元的描述,通过这些描述型字段我们可以和SQL非地理数据库进行相连,进行更详细的信息查询。
从地理数据库中查询到指定位置的设备的地理数据后,再根据地理数据中的附加属性和SQL数据库连接,就可以查询到一些更详细的附加信息了,在本模块的所以环节中,虽然SQL数据库检索是最繁琐的一部分,但是因为面临的实际技术问题单一,所以就不再详细介绍了。
图3.7 “分接箱”非地理数据表
在完成对地理数据库检索和非地理数据库检索后,就得到一个数据表集合,此时这个数据表集合,这个数据表集合就存储在MapIdentify控件的回调结果集合CallbackResults中,然后再通过GetCallbackResult接口函数将结果返回到客户端。具体实现方法如下:
…… CallbackResult cResponse = PointIdentify(map, mapPoint); //对指定位置的设备进行信息检索 CallbackResults.Add(cResponse);//父类WebControl的成员函数--一个stack类型的回调消息队列。 …… return base.GetCallbackResult();//返回回调结果至客户端 |
---|
3.客户端接收数据并进行显示
服务器端对客户端请求的数据进行回复后,客户端通过processCallbackResult客户端JavaScript函数来对回复的数据进行承接,并通过客户端的一个类似于MapTips的JavaScript控件进行显示,这个JavaScript控件主要由一个下拉框、一个检索信息显示表和一个图层路径提示条组成。下拉框是对要显示的图层进行选择,因为鼠标点击处可能有多个图层有满足要求的检索结果,检索信息显示表用来对下拉框中指定的图层的检索结果进行显示,图层路径提示条对当前显示的图层路径进行显示,具体效果如下图所示:
图3.8 地图交互查询效果图
客户端显示数据查询结果的JavaScript控件的基本功能模板已经给出,开发人员只需要找到传递数据的接口导入自己的数据,并对一些页面元素进行汉化就可以达到如上效果,所以具体过程也不再赘述了。
3.1.2 设备属性查询
要求:用户通过输入电力设备的已知属性(这些属性),比如“设备编号”、“设备名称”来进行关键字检索,将检索结果显示在页面中,然后选中的查询结果在地图中着重标识出来,并提供放大定位功能和查询详细信息。需要使用或者设置的Web ADF控件有:
SearchAttributesTask:用来承接来自服务输入的关键字并地图资源进行检索。
MapResourceManager:设置对地图数据源进行的查询参数。
TaskResults:任务结果,在页面中将查询结果以树形格式展现在,并提供一些其它基本功能。
TaskManager:将上述两种控件绑定――实现数据相关联。
1. SearchAttributesTask控件设置
利用系统自带的SearchAttributesTask控件经过简单的控件属性设置就可以满足本次毕业设计的要求,在页面中点击 SearchAttributesTask控件进行参数配置,会弹出如下的参数配置对话框:
图3.9 SearchAttributesTask控件设置界面
在“General”选项卡中对控件进行一些提示字符设置,在“Settings”选项卡中对地图检索字段范围进行设置(这个很重要),在“Results”选项卡中对查询结果纪录上限和显示方式进行设置(一般都采用默认选择)。
2.MapResourceManager相关设置
和地图数据源查询相关的一些设置。通过对MapResourceManger控件中的MapResourceItem中的LayerDefinition进行设置,设置界面如下:
图3.10 MapResourceManager设置界面
“Symbols”选项卡:查询结果高亮显示标记。
“Fields”选项卡:设置在TaskResults中需要显示的字段(例如FID,ID这些我们不关心的字段可以选择不显示)。
“Records”选项卡:设置TaskResults显示字段的别名(这是汉化的一部分工作)。
3. TaskResults自定义控件使用说明
系统提供的基本控件里面有如下缺点:
菜单项目固定,可扩展性太弱。
菜单提示默认英文的,难以找到接口进行汉化。
所以本次毕业设计中采用自定义的TaskResults控件的方式来进行对查询结果的显示,并对每条记录增加一些页面右击快捷菜单:“清除”,“放大定位”,“显示详细信息”。
在服务器端建立一个继承于ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl. TaskResults的类CustomTaskResults,然后就对其具体内容和功能进行编写了。在客户端代码中,和上面的“地图交互查询”控件一样,只需要在页面元素代码中加入一段控件名空间引用声明就可以了。
关于如何搭建此控件的基本平台,在安装ArcGIS时,有一段学习代码可以直接借鉴过来,所以在此就不再描述,本次毕业设计所解决的问题是向CustomTaskResults中对检索的每一条结果添加右键菜单命令:“清除”,“放大定位”,“显示详细信息”
首先在ArcGIS的开发帮助文档中查看TaskResults结构:
图3.11 TaskResults结构
不难发现,一个TaskResults提供了四种右键快捷菜单,分别是:
TaskResultContextMenu:是一个任务结果框架的最顶层右键菜单。
GraphicsLayerContextMenu:图层信息节点的右键菜单 ,处于第二层。
FeatureContextMenu: 图层下属要素结点的右键菜单,处于第三层。
RemoveOnlyContextMenu:当没有任何检索结果时,“空白提示”节点的右键菜单。
本次毕业设计中对三级菜单都做了自定义,由于篇幅原因,就只对实现第三级菜单的功能进行介绍,自定义FeatureContextMenu:
在重载过的CreateChildControls成员函数中对第三级菜单进行外观设置:
//判断是否成功自定义了右键菜单。
bool exists = false;
foreach (ContextMenuItem item in base.FeatureContextMenu.Items)
{
if (item.Text == "放大定位")
exists = true;
}
//如果没有,那么加入自定义的右键选项--三级目录
if (!exists)
{
base.FeatureContextMenu.Items.Clear();
contextmenu = base.FeatureContextMenu;
//放大
ContextMenuItem menuItemzoomin = new ContextMenuItem("images/show-magnify.png", "放大定位", "");
contextmenu.Items.Add(menuItemzoomin);
//清除
ContextMenuItem menuItemclear = new ContextMenuItem("images/dismiss_solid.png", "清除", "");
contextmenu.Items.Add(menuItemclear);
//显示
ContextMenuItem menuItemview = new ContextMenuItem("images/11.bmp", "显示设备详细信息", "");
contextmenu.Items.Add(menuItemview);
}
经过上面的定义后,在自定义的CustomTaskResults中的第三级节点上右击时会出现三个菜单:“放大定位”、“清除”、“显示设备详细信息”。但是点击这些命令还不会有任何反应,需要在其成员函数中OnLoad为这些命令增加对应的响应函数:
this.FeatureContextMenu.ItemClicked += new ContextMenuItemClickedEventHandler(FeatureContextMenu_ItemClicked); |
---|
函数FeatureContextMenu_ItemClicked就这样和第三级菜单事件绑定在一起了,只需要对此函数内部编写响应代码即可:
图3.12 服务器端快捷菜单响应函数代码框架图
三条命令的实现方法:
“放大定位”:
服务器端得到当前要素节点的信息,从中提取出几何点坐标,并设置一个以此几何点为中心的一定大小的封套(显然要比当前地图展示的范围要小,否则就不叫“放大”了),然后将地图控件的范围设置成此封套,并以此封套的中心为中心,就达到了“放大定位”的效果。具体实现流程图如下:
图3.13 实现“放大定位”功能流程
“清除”:
主要流程和“执行放大”一样,只是在服务器端的代码不同而已,只需要将CustomTaskResults中的Feature节点进行删除,然后再将命令加入到FeatureContextMenu的回调队列中,即可实现客户端对此节点的删除。
“显示设备详细信息”:
要求程序能够通过要素节点包含的地理信息到SQL数据库中检索得到更详细的信息,并在客户端浏览器中进行显示,CustomTaskResults的节点数据结构是一个XML字符串,因此可以通过对要素节点内容的XML文档进行解析(解析XML文档的方法在上一章进行了介绍)得到地理信息中的附加信息,此附加信息可用于连接SQL数据库,再通过要素节点的父节点名称可以得到需要检索的SQL表名称,于是可以得到详细的设备信息了。得到数据后,需要在客户端进行显示,为了达到比较好的客户端体验,显示方法选用网上比较流行的一款JavaScript对话框artDialog(关于artDialog的用法不是本文重点,所以不详细介绍了)。artDialog只需要传递一个div层的数据,然后调用JS函数打开对话框,就可以在客户端将指定的div里面的内容显示出来。本模块的主要实现流程图如下:
图3.14 实现“清除”功能流程
完成上述的菜单命令后,“设备属性查询”模块也就基本完成,效果图如下:
图3.15 “设备属性查询”运行效果图
------------------------------------------------------------------
Author:一点一滴的Beer
Email /Gtalk:dreamzsm@gmail.com
From:http://www.cnblogs.com/beer
Notes:欢迎转贴,但请在页面中加个链接注明出处