zoukankan      html  css  js  c++  java
  • ArcGIS Server 中的 Ajax技术的实现(举例说明)

     什么,你不懂Ajax,好吧,那么 在开始之前,我们先看下Ajax的定义,

       Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写。Ajax由几种已有技术以新的强大方式组合:基于XHTMLCSS标准的表示;使用Document Object Model进行动态显示和交互;使用XMLHttpRequest与服务器进行异步通信;使用JavaScript绑定一切。

          另外,我们来看看Callback机制,微软在ASP.NET 2.0中提出客户端Callback机制,其目的在于实现页面异步调用和无刷新局部显示。从技术角度分析,Callback机制就是对AJAX部分功能进行了封装(图2),其框架中提供全新接口ICallbackEventHandler用来指示控件作为服务器的回调事件的目标,通过接口的方法可轻松实现页面局部刷新技术。

    image

          ArcGIS Server在其最新的ArcGIS Server 9.2中为解决含有ADF组件页面局部刷新问题,在Asp.Net 2.0 Callback机制的基础上扩充引入了Ajax架构。所以从这点来看,.Net Callback 回调机制对于我们每一个学习ArcGIS Server 的人来说还是依然至关重要的!

          我们说Callback机制实际上就是一个接口ICallbackEventHandler,提供了两个方法,

          GetCallbackResult和RaiseCallbackEvent,其语法结构分别如下:

          string GetcallbackResult();

          void RaiseCallbackEvent(string eventArgument);

          前者返回以控件为目标的回调事件的结果,后者处理以控件为目标的回调事件,即执行回调事件。通过以上两个方法回调所实现的功能主要是:从客户端接收一个数据参数,在服务器端获取这个参数,并执行一个实现所需功能的事件,最后返回客户端所需结果数据。因此,如果要应用Callback机制,Page就必须继承接口ICallbackEventHandler。 通俗点说,RaiseCallbackEvent就是接收客户端的指令,然后对其进行处理,然后通过GetcallbackResult返回给客户端。

             另外,在.net中有一个函数可以使用客户端的脚本调用服务器端指定的函数。也就是通过这个方法才实现了.net中页面的无回调刷新的。

    public string GetCallbackEventReference (Control control,string argument,string clientCallback,string context)
    参数:
    control 处理客户端回调的服务器 Control。该控件必须实现 ICallbackEventHandler 接口并提供 RaiseCallbackEvent 方法。
    argument 从客户端脚本传递一个参数到服务器端的RaiseCallbackEvent 方法。
    clientCallback 一个客户端事件处理程序的名称,该处理程序接收服务器端事件返回的结果。
    context 启动回调之前在客户端的客户端脚本信息。脚本的结果传回给客户端事件处理程序。
    返回值 调用客户端回调的客户端函数的名称。
    返回服务器端的响应函数是没有选择的。必须是服务器端的RaiseCallbackEvent,因此当一个页面中有多个地方需要回调的时候,就需要使用参数来区分。
    客户端的响应函数使用javascripts来写,没有什么问题,在这里把返回的结果刷新出来。
    服务器端的实现代码放在RaiseCallbackEvent中,也没有什么问题。
    还有一个问题就是GetCallbackEventReference这个函数放在哪里,
    一个位置是放在page_load中,
    m_copyrightCallback = Page.ClientScript.GetCallbackEventReference(Page, "argument", "processCallbackResult", "context", true);
    另一个就是直接放在客户端的事件当中。

    <%=ClientScript.GetCallbackEventReference(this,"imagechange","ShowServerTime2",null) %>

    说了这么多,可能还是不太懂,我们举个例子来说明吧。

      

     

     

     

     

     

     

             本例子主要是先实现查询,查询结果显示在页面上的一个DIV中,然后将查询结果在地图上定位显示,在地图上显示这个过程是定位到所查询结果要素所在的那个区域, 并且实现时整个页面看起来不刷新(实际也是在刷新),只是地图在刷新。

    当然这个刷新的动态过程图片描述不出来,自己运行去看吧。 


     

    首先要加入map,mapresourcemanager,toolbar,toc等控件并设置关联,另外需要在mapresourcemanager 中除了自己的要用的地图外,还添加一个name为 Selection的资源,类型为GraphicsLayer, 其他操作都比较简单,在这里就省略了。

    1、加入html控件

        拖入一个html控件下的Text和两个Button 以及一个DIV,ID分别为:txtCommunitybtnCommunitybtnCommunity2,list1(其中Text用来输入查询的文字,btnCommunity用来查询,btnCommunity2用来在地图上地位,list1用来显示查询的结果)。然后分别单击获得两个Button的click事件,代码如下:

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

    function btnCommunity_onclick() {

          //获取输入的查询关键字
             var v=document.getElementById("txtCommunity").value;
             //生成请求字符串
             var argument = "ControlID=Map1&ControlType=Map&Type=queryC1&EventArg=" + v;
             var context = "Map";
             //m_Callback 由服务端的Page_load事件中生成的,用于请求服务端的js代码
             var script=<%= m_Callback %>
            //用eval执行字符串
            eval(script);

     

    }

    function btnCommunity2_onclick() {


    //获取输入的查询关键字

             var v=document.getElementById("txtCommunity").value;
             //生成请求字符串
             var argument = "ControlID=Map1&ControlType=Map&Type=queryC&EventArg=" + v;
             var context = "Map";
             //m_Callback 由服务端的Page_load事件中生成的,用于请求服务端的js代码
             var script=<%= m_Callback %>
            //用eval执行字符串
            eval(script);

    }

    //这个函数是用来实现查询结果的显示在页面中

    function gocenger(id)
          {
           //请求字符串
            var argument = "ControlID=Map1&ControlType=Map&Type=center&EventArg=" + id;
            var context = "Map";
            var script=<%= m_Callback %>
            eval(script);
         }

     </script>

    注意argument中的参数 ,其中Type与.cs文件的具体如何执行操作的判别有关,EventArg是从客户端传到服务器端的值(这里就是v的值)。

    2、在.cs中,首先要实现 ICallbackEventHandler接口,这是实现页面局部刷新的基础。

     public partial class _Default : System.Web.UI.Page, ICallbackEventHandler
        {
            
          
           


                    public string m_Callback = "";
           

            protected void Page_Load(object sender, EventArgs e)
            {
               

                //生成客户端脚本段
            m_Callback = Page.ClientScript.GetCallbackEventReference(Page, "argument", "processCallbackResult", "context", true);

                //这句话就是同上文所讲述的GetCallbackEventReference 的调用
                       }

                                          
                //以下就是实现的关键代码 ,可能有些垃圾代码,水平有限,请见谅。         

         #region ICallbackEventHandler 成员

            private string _callbackArg;
            //负责把结果回传给客户端
            string ICallbackEventHandler.GetCallbackResult()
            {
                return RaiseCallbackEvent(_callbackArg);
                
              

            }

            //负责从客户端javascript传来的参数
            void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
            {
                _callbackArg = eventArgument;

              

            }


            //对客户端的请求进行处理
            public virtual  string RaiseCallbackEvent(string _callbackArg)
            {

                   
                  
                   

                    string v = "";       //v 是用来最后传给客户端的结果
                   
                   
                 
                NameValueCollection keyValColl = CallbackUtility.ParseStringIntoNameValueCollection(_callbackArg);

                 //本例子是用来实现对地图中“社区”这一图层的查询,改成自己的数据即可,

     if (keyValColl["Type"].ToString() == "queryC1")//这个if中的语句用来实现查询的,
                        {

                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
                            string Input = keyValColl["EventArg"];//Input 即获得了页面中在Text 中输入的值


                            string str = "";

                            
                            string targetlayername = "社区";

                            //获取Data Layers的MapFunctionality
                            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;
                            //是否支持QueryFunctionality
                            bool supported = gisresource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));
                            if (supported)
                            {
                                //创建QueryFunctionality
                                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;
                                //查询图层的id和名称
                                qfunc.GetQueryableLayers(null, out lids, out lnames);

                                int layer_index = 0;
                                //获取目标图层的index
                                for (int i = 0; i < lnames.Length; i++)
                                {
                                    if (lnames[i] == targetlayername)
                                    {
                                        layer_index = i;
                                        break;
                                    }

                                }
                                //空间过滤
                                ESRI.ArcGIS.ADF.Web.SpatialFilter spatialfilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter();
                                //是否返回地理元素
                                spatialfilter.ReturnADFGeometries = false;
                                //返回最大记录数
                                spatialfilter.MaxRecords = 1000;
                                spatialfilter.Geometry = Map1.GetFullExtent();
                                //查询目标图层并且把结果存入DataTable
                                //查询语句
                                spatialfilter.WhereClause = " CommuName LIKE '" + Input + "%'";//这个 CommuName 字段改成自己数据中的字段即可
                               
                                System.Data.DataTable datatable = qfunc.Query(null, lids[layer_index], spatialfilter);

                                //组成显示内容
                                for (int i = 0; i < datatable.Rows.Count; i++)
                                {
                                    string idv = datatable.Rows[i]["FID"].ToString();

                                   
                                    string namev = datatable.Rows[i]["CommuName"].ToString();

                                    if (i == 0)
                                    {
                                        str = "<a href='#' onclick=gocenger('" + idv + "')>" + namev + "</a>";
                                    }
                                    else
                                    {
                                        str = str + "<br/>" + "<a href='#' onclick=gocenger('" + idv + "')>" + namev + "</a>";
                                    }

                                }

                                //重新获得Map1控件所有的 functionality
                                IEnumerable gfc = Map1.GetFunctionalities();
                                ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource gResource = null;
                                foreach (IGISFunctionality gfunc in gfc)
                                {
                                    //找到名为"Selection"的MapResource
                                    if (gfunc.Resource.Name == "Selection")
                                    {
                                        //down cast到 ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource
                                        gResource = (ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)gfunc.Resource;
                                    }
                                }

                                if (gResource == null)
                                    return null;

                                ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer glayer = null;

                                foreach (System.Data.DataTable dt in gResource.Graphics.Tables)
                                {
                                    if (dt is ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer)
                                    {
                                        glayer = (ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer)dt;
                                        break;
                                    }
                                }

                                if (glayer == null)
                                {
                                    glayer = new ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer();

                                    gResource.Graphics.Tables.Add(glayer);
                                }

                                //清除已有数据
                                glayer.Clear();

                                DataRowCollection drs = datatable.Rows;

                                int shpind = -1;
                                for (int i = 0; i < datatable.Columns.Count; i++)
                                {
                                    if (datatable.Columns[i].DataType == typeof(ESRI.ArcGIS.ADF.Web.Geometry.Geometry))
                                    {
                                        //找到Geometry 字段的序号
                                        shpind = i;
                                        break;
                                    }
                                }

                                try
                                {
                                    foreach (DataRow dr in drs)
                                    {
                                        ESRI.ArcGIS.ADF.Web.Geometry.Geometry geom = (ESRI.ArcGIS.ADF.Web.Geometry.Geometry)dr[shpind];

                                        //创建一个 GraphicElement
                                        ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement ge = null;
                                        ge = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(geom, System.Drawing.Color.Red);
                                        ge.Symbol.Transparency = 50.0;

                                        //将 GraphicElement添加到ElementGraphicsLayer中
                                        glayer.Add(ge);
                                        Map1.Extent = glayer.FullExtent;
                                    }
                                }
                                catch (InvalidCastException ice)
                                {
                                    throw new Exception("No geometry available in datatable");
                                }

                                if (Map1.ImageBlendingMode == ImageBlendingMode.WebTier)
                                {
                                    Map1.Refresh();

                                }
                                else if (Map1.ImageBlendingMode == ImageBlendingMode.Browser)
                                {
                                    //只刷新Graphics Resource
                                    Map1.RefreshResource(gResource.Name);
                                }


                                int n = datatable.Rows.Count;
                                if (n < 1)
                                {
                                    str = "<a href='#' onclick=gocenger('" + 0 + "')>" + "找不到相关记录!" + "</a>";

                                    sb.AppendFormat("div:::{0}:::innercontent:::{1}", "list1", str);
                                   
                                   // this.ListBox1.Items.Add(new ListItem("找不到相关记录"));
                                  
                                    v = sb.ToString();

                                    return v;

                                }


                            }

                            sb.AppendFormat("div:::{0}:::innercontent:::{1}", "list1", str);  //查询到的结果就是显示在list1中的
                           

                            v = sb.ToString();

                            

                            return v;     //将查询到的结果及显示方式传回到客户端


                        }

             
            else  if (keyValColl["Type"].ToString() == "queryC")//这个if语句用来实现查询结果在地图上定位的
                        {

                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
                            string Input = keyValColl["EventArg"]; 
                            string str = "";

                           
                            string targetlayername = "社区";

                            //获取Data Layers的MapFunctionality
                            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;
                            //是否支持QueryFunctionality
                            bool supported = gisresource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));
                            if (supported)
                            {
                                //创建QueryFunctionality
                                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;
                                //查询图层的id和名称
                                qfunc.GetQueryableLayers(null, out lids, out lnames);

                                int layer_index = 0;
                                //获取目标图层的index
                                for (int i = 0; i < lnames.Length; i++)
                                {
                                    if (lnames[i] == targetlayername)
                                    {
                                        layer_index = i;
                                        break;
                                    }

                                }
                                //空间过滤
                                ESRI.ArcGIS.ADF.Web.SpatialFilter spatialfilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter();
                                //是否返回地理元素
                                spatialfilter.ReturnADFGeometries = false;
                                //返回最大记录数
                                spatialfilter.MaxRecords = 1000;
                                spatialfilter.Geometry = Map1.GetFullExtent();
                                //查询目标图层并且把结果存入DataTable
                                //查询语句
                               

                                spatialfilter.WhereClause = " CommuName LIKE '" + Input + "%'";  
                              
                                System.Data.DataTable datatable = qfunc.Query(null, lids[layer_index], spatialfilter);

                               

                                //重新获得Map1控件所有的 functionality
                                IEnumerable gfc = Map1.GetFunctionalities();
                                ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource gResource = null;
                                foreach (IGISFunctionality gfunc in gfc)
                                {
                                    //找到名为"Selection"的MapResource
                                    if (gfunc.Resource.Name == "Selection")
                                    {
                                        //down cast到 ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource 
                                         //将查询到的结果存到"Selection"的MapResource 中
                                    gResource = (ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)gfunc.Resource;

                                       }
                                }

                                if (gResource == null)
                                    return null;

                                ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer glayer = null;

                                foreach (System.Data.DataTable dt in gResource.Graphics.Tables)
                                {
                                    if (dt is ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer)
                                    {
                                        glayer = (ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer)dt;
                                        break;
                                    }
                                }

                                if (glayer == null)
                                {
                                    glayer = new ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer();

                                    gResource.Graphics.Tables.Add(glayer);
                                }

                                //清除已有数据
                                glayer.Clear();

                                DataRowCollection drs = datatable.Rows;

                                int shpind = -1;
                                for (int i = 0; i < datatable.Columns.Count; i++)
                                {
                                    if (datatable.Columns[i].DataType == typeof(ESRI.ArcGIS.ADF.Web.Geometry.Geometry))
                                    {
                                        //找到Geometry 字段的序号
                                        shpind = i;
                                        break;
                                    }
                                }

                                try
                                {
                                    foreach (DataRow dr in drs)
                                    {
                                        ESRI.ArcGIS.ADF.Web.Geometry.Geometry geom = (ESRI.ArcGIS.ADF.Web.Geometry.Geometry)dr[shpind];

                                        //创建一个 GraphicElement
                                        ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement ge = null;
                                        ge = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(geom, System.Drawing.Color.Red);
                                        ge.Symbol.Transparency = 50.0;

                                        //将 GraphicElement添加到ElementGraphicsLayer中
                                        glayer.Add(ge);
                                        Map1.Extent = glayer.FullExtent;//将地图的显示范围该变为查询结果要素的范围

                               //若是查询到的结果为点,上面这句话要改成以下这段语句:

                      //double x1 =glayer.FullExtent.XMax+25;
                    // double x2=glayer.FullExtent.XMin-25;
                     //double  y1= glayer.FullExtent.YMax+25;
                    // double y2=glayer.FullExtent.YMin-25;
                    // ESRI.ArcGIS.ADF.Web.Geometry.Envelope pEnv = new ESRI.ArcGIS.ADF.Web.Geometry.Envelope();
                    //   pEnv.XMin =x2;
                    //   pEnv.XMax = x1;
                    //   pEnv.YMin=y2;
                     //  pEnv.YMax = y1;
                    
                      // Map1.Extent =pEnv.Expand(1);
                     
                 


                                    }
                                }
                                catch (InvalidCastException ice)
                                {
                                    throw new Exception("No geometry available in datatable");
                                }

                                if (Map1.ImageBlendingMode == ImageBlendingMode.WebTier)
                                {
                                    Map1.Refresh();

                                }
                                else if (Map1.ImageBlendingMode == ImageBlendingMode.Browser)
                                {
                                    //只刷新Graphics Resource
                                    Map1.RefreshResource(gResource.Name);
                                }


                                

                                
                            }


                            v = Map1.CallbackResults.ToString();

                            return v;           //返回了查询结果显示的内容及其显示范围


                        }

                         3、好了,大体上就是这些步骤,2中有很多的注释看起来有点乱,但是一般是写在代码的对应地方,我觉得这样可能易于理解,请见谅!

                 本文中例子的版权属于千秋一统哦!

           

     

     

     
    一起学习GIS及其二次开发,一起进步!
  • 相关阅读:
    Python基础---线程
    virtualenv和virtualenvwrapper的安装和使用
    微信公众号实现简易的物联网控制(二)
    PyQt5之SQLite数据库操作(1)
    PyQt5无边框后窗口的移动方法
    PyQt5显示GIF图片
    Python显示进度条的方法
    WinSCP默认使用root用户登录的方法
    微信公众号实现简易的物联网控制(一)
    Arduino语音天气预报(三)
  • 原文地址:https://www.cnblogs.com/tuncaysanli/p/1328551.html
Copyright © 2011-2022 走看看