ArcGIS Server 开发系列(五)--自定义 Toolbar 工具 (转载于Flyingis)


前面的开发系列均是使用server开发模板程序Web Mapping Application,工具条上的基本工具是已经在模板中定制好的,在实际项目应用中,我们需要的工具远远不仅如此,如何在工具条中增加新的自定义工具是开发系列(五)所要描述的,其中使用ASP.Net 2.0 Callback framework进行异步刷新地图是重点。

目标:
自定义工具按钮进行矩选查询,高亮显示所选择的地图要素,页面下方的Gridview显示所选择要素的属性信息。

准备工作:
1.了解ESRI.ArcGIS.Server.WebControls.IMapServerToolAction接口
2.了解ASP.Net 2.0 Callback framework
3.新建一个网站,在ArcGIS Web Controls控件中拖动如下控件:Toolbar、Map、Toc、MapResourceManager,以及常用控件Label、DropDownList、Gridview。
4.设置控件属性,Toolbar、Toc的BuddyControls均为Map1,Toolbar的BuddyControlType为Map,Map控件的MapResourceManager为MapResourceManager1。
5.更改MapResourceManager属性,添加两个Resource:Selection和NorthAmerica,类型分别是Graphics Layer和ArcGIS Server Internet。
最后视图效果:


思路:

现在重新想想我们要做什么,首先要自定义一个工具按钮,使用该工具后在地图上进行矩形选择,对选择的要素高亮显示,同时gridview显示出这些要素的属性信息。整个过程看似容易,实际上需要在客户端和服务器端之间来回切换,异步调用,这里用到了ASP.Net Callback framework,其实Server中很多地图操作都基于asp.net callback,或是实现了ICallbackEventHandler接口,理解了这一段程序开发有利于深入了解Server地图刷新、Task等组件的工作机制。

首先在Toolbar上新增一个按钮Select Features,上图其实已经加入了,加入的方法是,选择Toolbar控件属性ToobarItems,添加一个Tool,设置以下值:

Text:Select Feature
CientAction:DragRectangle
Name:SelectTool
ServerActionAssembly:App_Code
ServerActionClass:SelectFeatures

OK,搞定!

除了上述属性外,还可以设置该按钮各种状态下的图片显示、ToolTip等等,这里就省了,纵观这些属性,可以看出既有js脚本的交互(已经封装了,通过 ToolEventArgs传入),也有服务器端功能的实现,这时我们需新建一个类SelectFeatures,并实现 IMapServerToolAction接口,类中实现IMapServerToolAction的方法ServerAction。
publicclassSelectFeatures:IMapServerToolAction{
publicvoidServerAction(ToolEventArgsargs)
}

代码实现:

1.获取矩形框的屏幕坐标

要查询矩选的地图信息,首先应知道矩形的坐标,在服务器端如何获取呢?
Mapmapctrl=null;
mapctrl
=(Map)args.Control;
//获取下拉框中的数据,在后面实现
stringtargetlayername=(string)mapctrl.Page.Session["TargetLayer"];

RectangleEventArgsrectargs
=null;
//强制类型转换为RectangleEventArgs
rectargs=(RectangleEventArgs)args;

//获取矩形选择框的屏幕坐标
System.Drawing.Rectanglerect=rectargs.ScreenExtent;
ESRI.ArcGIS.ADF.Web.Geometry.Pointminpnt
=ESRI.ArcGIS.ADF.Web.Geometry.Point.ToMapPoint(rect.Left,rect.Bottom,mapctrl.Extent,(int)mapctrl.Width.Value,(int)mapctrl.Height.Value);
ESRI.ArcGIS.ADF.Web.Geometry.Pointmaxpnt
=ESRI.ArcGIS.ADF.Web.Geometry.Point.ToMapPoint(rect.Right,rect.Top,mapctrl.Extent,(int)mapctrl.Width.Value,(int)mapctrl.Height.Value);

ESRI.ArcGIS.ADF.Web.Geometry.Envelopemappoly
=null;
//minpnt、maxpnt分别是左下、右上坐标点
mappoly=newESRI.ArcGIS.ADF.Web.Geometry.Envelope(minpnt,maxpnt);
所有的信息都是通过args获取,它是一个ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs对象,包含了客户端Map控件和当前客户端工具的信息,RectangleEventArgs是它的子类,强制性转换后得到矩选的矩形坐标,最后得到一个 Envelope,用于spatialfilter.Geometry属性。

2.查询所选择的要素并对Graphics Layer进行渲染实现高亮

这部分内容完全可以参考《ArcGIS Server 开发系列(三)--漫游 Graphics data sources》,只需要注释掉WhereClause属性赋值,再增加一行代码:
ESRI.ArcGIS.ADF.Web.SpatialFilterspatialfilter=newESRI.ArcGIS.ADF.Web.SpatialFilter();
spatialfilter.ReturnADFGeometries
=false;
spatialfilter.MaxRecords
=1000;
//spatialfilter.WhereClause=txtQuery.Text;
spatialfilter.Geometry=mappoly;
3.异步刷新Gridview显示地图要素的属性
GridViewgdview=(GridView)mapctrl.Page.FindControl("GridView1");

object[]oa=newobject[1];
stringshowtable="'visible'";

//datatable为矩选时所选择的地图要素,绑定到gridview
gdview.DataSource=datatable;
gdview.DataBind();

stringreturnstring=null;

using(System.IO.StringWritersw=newSystem.IO.StringWriter())
{
HtmlTextWriterhtw
=newHtmlTextWriter(sw);
gdview.RenderControl(htw);
htw.Flush();
returnstring
=sw.ToString();
}


//innercontent相当于innerhtml
CallbackResultcr=newCallbackResult("div","griddiv","innercontent",returnstring);
//通过回调将信息从服务器端传输到客户端
mapctrl.CallbackResults.Add(cr);

if(datatable.Rows.Count>1)
{
showtable
="'visible'";
}

else
{
showtable
="'hidden'";
}


stringsa="vargriddiv=document.getElementById('griddiv');";
sa
+="griddiv.style.visibility="+showtable+";";
oa[
0]=sa;

CallbackResultcr1
=newCallbackResult(null,null,"javascript",oa);
mapctrl.CallbackResults.Add(cr1);

这段代码最关键的类是CallbackResult,它简化了web adf framework中客户端回调的处理,不用再创建自己的客户端和服务器端逻辑,使用CallbackResult就可以将信息传回客户端,更新客户端页面的内容、图片或执行js脚本。关于CallbackResult构造方法第三个参数,下面js代码写的很详细:
if(action=="content"){
o
=document.getElementById(actions[1]);
if(o!=null)
{
o.outerHTML
=actions[3];
}

}

elseif(action=="innercontent"){
o
=document.getElementById(actions[1]);
if(o!=null)
{
o.innerHTML
=actions[3];
}

}

elseif(action=="image")
{
o
=document.images[actions[1]];
if(o!=null)
{
o.src
=actions[3];
}

elsealert(actions[1]+"wasnull");
}

elseif(action=="javascript"){
eval(actions[
3]);
}

4.填充DropDownList

DropDownList显示的是ArcGIS Server Internet地图数据源所包含的图层名称,选择哪个图层,矩选时就对哪个图层进行查询,DropDownList的填充在Page_PreRender过程中。
if(!IsPostBack)
{
ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionalitymf
=(ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality)Map1.GetFunctionality(1);

ESRI.ArcGIS.ADF.Web.DataSources.IGISResourcegisresource
=mf.Resource;
boolsupported=gisresource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));

if(supported)
{
ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionalityqfunc
=(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)gisresource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality),null);

string[]lids;
string[]lnames;
qfunc.GetQueryableLayers(
null,outlids,outlnames);
for(inti=0;i<lnames.Length;i++)
{
LayerDropDownList1.Items.Add(lnames[i]);
}

Session[
"TargetLayer"]=LayerDropDownList1.Items[0].Value;
}

}

5.实现ICallbackEventHandler接口

Default.aspx.cs的_Default实现ICallbackEventHandler接口,在类中实现RaiseCallbackEvent和GetCallbackResult两个方法,做ASP.Net 2.0的对ICallbackEventHandler应该是再熟悉不过了:)但下来框显示图层为什么要用到callback?
protectedvoidPage_Load(objectsender,EventArgse)
{
if(!IsPostBack)
{
Session[
"TargetLayer"]="";
}

LayerDropDownList1.Attributes.Add(
"onchange","ChangeLayer()");
sADFCallBackFunctionInvocation
=Page.ClientScript.GetCallbackEventReference(this,"message","processCallbackResult","context","postBackError",true);
}


publicvoidChangeDropDownListServer(stringea)
{
char[]parser_char={','};
string[]messages=ea.Split(parser_char);
stringdll1=messages[1];
Session[
"TargetLayer"]=dll1;
}


#regionICallbackEventHandler成员
publicvoidRaiseCallbackEvent(stringeventArgument)
{
if(eventArgument.Contains("ddl1"))
{
ChangeDropDownListServer(eventArgument);
}

}

publicstringGetCallbackResult()
{
returnreturnstring;
}

原因就在这里,改变Session ["TargetLayer"]的值,SelectFeatures需要知道是对哪个图层进行查询的,从而对在那个图层选择要素进行高亮及属性显示,这里 callback仅仅是在做了变量值的处理。最后在页面之间加入js脚本ChangeLayer()。
<scripttype="text/javascript"language="javascript">
varcontext;
functionChangeLayer()
{
varmessage;
varddl1value=document.getElementById('LayerDropDownList1').value;
message
='ddl1';
message
+=','+ddl1value;
<%=sADFCallBackFunctionInvocation%>
}

</script>
运行程序:


其中黄色区域就是Select Features按钮矩选的要素,下方gridview显示了查询到的属性结果。

程序中有两个地方用到了异步刷新,一个是ASP.Net 2.0原有接口ICallbackEventHandler,另一个是Web ADF framework的CallbackResult类,最初认为简单异步刷新用自己写的XMLHttpRequest请求更为简单,如上例中对 session存储值的改变,不用ICallbackEventHandler,但是在server地图互操作的过程中, ICallbackEventHandler给我们提供了更多的便利。

继续思考:

1.本例实现了根据地图查询属性,反过来根据属性查询几何图形怎么实现呢?其实前面《ArcGIS Server 开发系列(三)--漫游 Graphics data sources》已经讲到了,只不过需要将条件查询的信息,更改为在gridview或其他地方选择的属性信息,然后高亮显示相应的几何要素。

2.这种几何要素图形和属性信息的关联可以应用于各种不同的业务需求中,如图形和属性的同步删除、位置定位、类似结果查询等等。

3.如何改进或提升这种图形和属性的异步刷新带来的用户体验? 优质内容筛选与推荐>>
1、[web] lucene 搜索入门
2、交换与路由第二章 IP编址
3、免费shadowsockX日常查查谷歌资料是没问题的
4、如何不做伪phper
5、Python开发【第一篇】Python基础之函数递归


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn