全国高分辨率土地利用数据服务 土地利用数据服务 土地覆盖数据服务 坡度数据服务 土壤侵蚀数据服务 全国各省市DEM数据服务 耕地资源空间分布数据服务 草地资源空间分布数据服务 林地资源空间分布数据服务 水域资源空间分布数据服务 建设用地空间分布数据服务 地形、地貌、土壤数据服务 分坡度耕地数据服务 全国大宗农作物种植范围空间分布数据服务
多种卫星遥感数据反演植被覆盖度数据服务 地表反照率数据服务 比辐射率数据服务 地表温度数据服务 地表蒸腾与蒸散数据服务 归一化植被指数数据服务 叶面积指数数据服务 净初级生产力数据服务 净生态系统生产力数据服务 生态系统总初级生产力数据服务 生态系统类型分布数据服务 土壤类型质地养分数据服务 生态系统空间分布数据服务 增强型植被指数数据服务
多年平均气温空间分布数据服务 多年平均降水量空间分布数据服务 湿润指数数据服务 大于0℃积温空间分布数据服务 光合有效辐射分量数据服务 显热/潜热信息数据服务 波文比信息数据服务 地表净辐射通量数据服务 光合有效辐射数据服务 温度带分区数据服务 山区小气候因子精细数据服务
全国夜间灯光指数数据服务 全国GDP公里格网数据服务 全国建筑物总面积公里格网数据服务 全国人口密度数据服务 全国县级医院分布数据服务 人口调查空间分布数据服务 收入统计空间分布数据服务 矿山面积统计及分布数据服务 载畜量及空间分布数据服务 农作物种植面积统计数据服务 农田分类面积统计数据服务 农作物长势遥感监测数据服务 医疗资源统计数据服务 教育资源统计数据服务 行政辖区信息数据服务
Landsat 8 高分二号 高分一号 SPOT-6卫星影像 法国Pleiades高分卫星 资源三号卫星 风云3号 中巴资源卫星 NOAA/AVHRR MODIS Landsat TM 环境小卫星 Landsat MSS 天绘一号卫星影像
前面的开发系列均是使用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
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;
// minpnt、maxpnt分别是左下、右上坐标点
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接口,在类中实现RaiseCallbackEvent和GetCallbackResult两个方法,做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 framework的CallbackResult类,最初认为简单异步刷新用自己写的XMLHttpRequest请求更为简单,如上例中对 session存储值的改变,不用ICallbackEventHandler,但是在server地图互操作的过程中, ICallbackEventHandler给我们提供了更多的便利。