『公告』 预祝您龙年大吉,万事如意, 过节期间, 大家如需数据服务,请拨打400 或直接添加客服微信,再祝大家龙年,心想事成。
关注我们 新浪 腾讯

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

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

       前面的开发系列均是使用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控件中拖动如下控件:ToolbarMapTocMapResourceManager,以及常用控件LabelDropDownListGridview

       4.设置控件属性,ToolbarTocBuddyControls均为Map1ToolbarBuddyControlTypeMapMap控件的MapResourceManagerMapResourceManager1

       5.更改MapResourceManager属性,添加两个ResourceSelectionNorthAmerica,类型分别是Graphics LayerArcGIS Server Internet

    最后视图效果:

 

       思路:

 

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

 

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

 

    Text:Select Feature

    CientActionragRectangle

    Name:SelectTool

    ServerActionAssembly:App_Code

    ServerActionClass:SelectFeatures

   

       OK,搞定!

 

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

public

class SelectFeatures : IMapServerToolAction {

    public

void ServerAction(ToolEventArgs args)

}

 

       代码实现:

 

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

 

       要查询矩选的地图信息,首先应知道矩形的坐标,在服务器端如何获取呢?

Map mapctrl = null;

mapctrl = (Map)args.Control;

// 获取下拉框中的数据,在后面实现

string targetlayername = (string)mapctrl.Page.Session["TargetLayer"];

 

RectangleEventArgs rectargs = null;

// 强制类型转换为RectangleEventArgs

rectargs = (RectangleEventArgs)args;

 

// 获取矩形选择框的屏幕坐标

System.Drawing.Rectangle rect = rectargs.ScreenExtent;

ESRI.ArcGIS.ADF.Web.Geometry.Point minpnt = 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.Point maxpnt = 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.Envelope mappoly = null;

// minpntmaxpnt分别是左下、右上坐标点

mappoly = new ESRI.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.SpatialFilter spatialfilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter();

spatialfilter.ReturnADFGeometries = false;

spatialfilter.MaxRecords = 1000;

//spatialfilter.WhereClause = txtQuery.Text;

spatialfilter.Geometry = mappoly;

 

       3.异步刷新Gridview显示地图要素的属性

GridView gdview = (GridView)mapctrl.Page.FindControl("GridView1");

 

object[] oa = new

object[1];

string showtable = "'visible'";

 

// datatable为矩选时所选择的地图要素,绑定到gridview

gdview.DataSource = datatable;

gdview.DataBind();

 

string returnstring = null;

 

using (System.IO.StringWriter sw = new System.IO.StringWriter())

{

HtmlTextWriter htw = new HtmlTextWriter(sw);

gdview.RenderControl(htw);

htw.Flush();

returnstring = sw.ToString();

}

 

// innercontent相当于innerhtml

CallbackResult cr = new CallbackResult("div", "griddiv", "innercontent", returnstring);

// 通过回调将信息从服务器端传输到客户端

mapctrl.CallbackResults.Add(cr);

 

if (datatable.Rows.Count > 1)

{

showtable = "'visible'";

}

else

{

showtable = "'hidden'";

}

 

string sa = "var griddiv = document.getElementById('griddiv');";

sa += "griddiv.style.visibility = "

+ showtable +

";";

oa[0] = sa;

 

CallbackResult cr1 = new CallbackResult(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];

}

}

else

if (action=="innercontent") {

o = document.getElementById(actions[1]);

if (o != null)

{

o.innerHTML=actions[3];

}

}

else

if (action=="image")

{

o = document.images[actions[1]];

if (o != null)

{

o.src = actions[3];

}

else alert (actions[1] +

" was null");

}

else

if (action=="javascript") {

eval(actions[3]);

}

 

       4.填充DropDownList

 

       DropDownList显示的是ArcGIS Server Internet地图数据源所包含的图层名称,选择哪个图层,矩选时就对哪个图层进行查询,DropDownList的填充在Page_PreRender过程中。

if (!IsPostBack)

{

    ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mf = (ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality)Map1.GetFunctionality(1);

 

    ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisresource = mf.Resource;

    bool supported = gisresource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));

 

    if (supported)

    {

        ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality qfunc = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)gisresource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);

 

        string[] lids;

        string[] lnames;

        qfunc.GetQueryableLayers(null, out lids, out lnames);

        for (int i =

0; i < lnames.Length; i++)

        {

            LayerDropDownList1.Items.Add(lnames);

        }

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

    }

}

 

       5.实现ICallbackEventHandler接口

 

       Default.aspx.cs_Default实现ICallbackEventHandler接口,在类中实现RaiseCallbackEventGetCallbackResult两个方法,做ASP.Net 2.0的对ICallbackEventHandler应该是再熟悉不过了但下来框显示图层为什么要用到callback

protected void Page_Load(object sender, EventArgs e)

{

    if (!IsPostBack)

    {

        Session["TargetLayer"] = "";

    }

    LayerDropDownList1.Attributes.Add("onchange", "ChangeLayer()");

    sADFCallBackFunctionInvocation = Page.ClientScript.GetCallbackEventReference(this, "message", "processCallbackResult", "context", "postBackError", true);

}

 

public void ChangeDropDownListServer(string ea)

{

    char[] parser_char = { ',' };

    string[] messages = ea.Split(parser_char);

    string dll1 = messages[1];

    Session["TargetLayer"] = dll1;

}

 

ICallbackEventHandler 成员#region ICallbackEventHandler 成员

public void RaiseCallbackEvent(string eventArgument)

{

    if (eventArgument.Contains("ddl1"))

    {

    ChangeDropDownListServer(eventArgument);

    }

}

public

string GetCallbackResult()

{

    return returnstring;

}

 

       原因就在这里,改变Session ["TargetLayer"]的值,SelectFeatures需要知道是对哪个图层进行查询的,从而对在那个图层选择要素进行高亮及属性显示,这里 callback仅仅是在做了变量值的处理。最后在页面之间加入js脚本ChangeLayer()

<script type="text/javascript" language="javascript">

var context;

function ChangeLayer()

{

    var message;

    var ddl1value = document.getElementById('LayerDropDownList1').value;

    message = 'ddl1';

    message += ',' + ddl1value;

    <%=sADFCallBackFunctionInvocation%>

}

</script>

 

       运行程序:

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

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

      京ICP备2025132830号-1 京公网安备 号