zoukankan      html  css  js  c++  java
  • 一个下拉联动控件的实现

    联动下拉菜单是我们平时做web开发时经常会遇到的一种情况。有多种实现的方式。比如数据一次加载在客户端联动或者回调填充。前段时间要给部门内部做个简单的培训用到相关的javascript和控件开发的时候,就那这个当作demo来做了。控件大概有4个部分组成,
    1:控件的cs代码(AutoFillDDL.cs),2:客户端回应服务器段返回的数据,构建Option的js(AutoFill.js),3.服务器段写获取数据的方法的接口(IXBCallbackHandler)4。发送xmlHTTP请求的类的js(NetLoad.js)
    AutoFillDDL.cs

      1using System;
      2using System.Collections.Generic;
      3using System.Text;
      4using System.Web.UI.WebControls;
      5using System.Web.UI;
      6using System.ComponentModel;
      7using Beyondbit.Soft3.WebControl.Designer;
      8
      9[assembly: WebResource("Beyondbit.Soft3.WebControl.Js.AutoFill.js""application/x-javascript")]
     10[assembly: WebResource("Beyondbit.Soft3.WebControl.Js.NetLoad.js""application/x-javascript")]
     11namespace Beyondbit.Soft3.WebControl
     12{
     13    public class AutoFillDDL : Label
     14    {
     15
     16        private string _controlfromrelation = "";
     17        [TypeConverter(typeof(AutoFillControlConvert)), IDReferenceProperty, Category("Behavior"), Themeable(false), DefaultValue(""), Description("需要联动的父的控件")]
     18        public string ControlFromRelation
     19        {
     20            get
     21            {
     22                return _controlfromrelation;
     23            }

     24            set
     25            {
     26                _controlfromrelation = value;
     27            }

     28        }

     29
     30        private string _controltorelation = "";
     31        [TypeConverter(typeof(AutoFillControlConvert)), IDReferenceProperty, Category("Behavior"), Themeable(false), DefaultValue(""), Description("需要联动的子的控件")]
     32        public string ControlToRelation
     33        {
     34            get
     35            {
     36                return _controltorelation;
     37            }

     38            set
     39            {
     40                _controltorelation = value;
     41            }

     42        }

     43
     44
     45        方法 
     89    
     90    
     91        private string XBGetCallbackResult(string eventArgument,string callbackId)
     92        {
     93            return GetJsonStringFromList(GetIXBCallBackReslut(eventArgument, callbackId));                       
     94        }
       
     95
     96    
     97        protected virtual List<ListItem> GetIXBCallBackReslut(string eventArgument, string callbackId)
     98        {
     99            string[] arrArg = eventArgument.Split('|');
    100            if (arrArg.Length == 2)
    101            {
    102                ListItem list = new ListItem();
    103                list.Text  = arrArg[0!= null && arrArg[0!=""  ? arrArg[0] : "" ;
    104                list.Value = arrArg[1!= null && arrArg[1!= "" ? arrArg[1] : "";                
    105                if (this is IXBCallbackHandler)  //控件内部实现了接口那么使用控件内部的方法,用于其他继承该控件的子控件
    106                {
    107                    return ((IXBCallbackHandler)this).GetIXBCallBackReslut(list, callbackId);
    108                }

    109                else if (this.Page is IXBCallbackHandler)  //页面实现了接口
    110                {
    111                    return ((IXBCallbackHandler)this.Page).GetIXBCallBackReslut(list, callbackId); ;
    112                }

    113                else //其他则提示
    114                {
    115                    List<ListItem> lists = new List<ListItem>();
    116                    lists.Add(new ListItem("没有实现IXBCallbackHandler接口"""));
    117                    return lists;
    118                }

    119            }

    120            else //下拉表的值或者字中不能包含|字符,也可以用其他字符代替
    121            {
    122                List<ListItem> lists = new List<ListItem>();
    123                lists.Add(new ListItem("发生意外错误,可能是你的名称或的值里面包含|"""));
    124                return lists;
    125            }

    126
    127        }
       
    128        //拼接json字符串
    129        protected internal static string GetJsonStringFromList(List<ListItem> list)
    130        {
    131            if (list.Count == 0return "";
    132
    133            StringBuilder sb = new StringBuilder() ;
    134            sb.AppendLine("{options:[");
    135            for(int i = 0 ,j =list.Count;i<j ;i++)
    136            {
    137                if( i !=0 ) sb.AppendLine(",") ;
    138                sb.AppendLine("{");
    139                sb.AppendLine("Text:\""+list[i].Text+"\",");           
    140                sb.AppendLine("Value:\""+list[i].Value+"\"");
    141                sb.AppendLine("}");
    142            }

    143            sb.AppendLine("]}");
    144            return sb.ToString();
    145        }
           
    146    }

    147}

    AutoFill.js

     1//构造函数,用于声明该类 
     2function AutoFill(control,fromDll,toDll){
     3    this._control=control;  //联动控件的clientID       
     4    //获取联动的发起的下拉表对象
     5    this._fromddllobj=document.all?document.all[fromDll]:document.getElementById(fromDll);
     6    //响应联动的下拉表对象
     7    this._todllobj=document.all?document.all[toDll]:document.getElementById(toDll);
     8    //为解决闭包的问题,把AutoFill的实例付给下拉表对象的一个临时变量
     9    this._fromddllobj.af=this;  
    10    //给下拉表附加onchange事件 ,原想使用AttachEvent的方法,
    11    //但是这样的附加this的取值就会有问题 ,非下拉表本身而是window对象,
    12    //不知道微软在实现上是否有问题,或者是我有问题?
    13    this._fromddllobj.onchange = function (){  
    14        //当onchange的时候 触发该函数
    15        this.af.ajaxfun(this.af._control,this.options[this.selectedIndex].text+"|"+this.options[this.selectedIndex].value,this.af._todllobj); 
    16    }
    ;    
    17}
    ;
    18AutoFill.prototype.ajaxfun=function (control,arg,childDll){    
    19    //关于NetLoad,请参阅NetLoad.js
    20    var ajax = new NetLoad();
    21    var url=ajax.GetPesentUrl() ;   //获取发送的url地址
    22    url +=url.indexOf("?")>0?"&":"?" ;
    23    url +="Action=AutoFill_GetData&__CALLBACKID="+this.Encode(control)+"&__CALLBACKPARAM="+this.Encode(arg) ;
    24    ajax.url =url ;
    25    ajax.method="get";    
    26    ajax.OpbackObj = childDll ;//回调函数中需要处理的下拉表,也就是  _todllobj对象
    27    ajax.callback =this.buildToDDL ;//回调函数
    28    ajax.send();    //发送请求
    29}
    ;
    30AutoFill.prototype.Encode = function(parameter)
    31{
    32    if (encodeURIComponent) {
    33        return encodeURIComponent(parameter);
    34    }

    35    else {
    36        return escape(parameter);
    37    }

    38}

    39AutoFill.prototype.buildToDDL=function (ret,opObj){
    40    if(!opObj){
    41        alert("Error:\nPlease Check Your RP Then Try Again");
    42        return ;
    43    }
    ;
    44    try{      
    45        if(ret.responseText == null || ret.responseText ==""return ;        
    46        //接受回发的json字符串,并付给该对象 ,可查看图片
    47        var json=eval(ret.responseText);
    48        opObj.options.length = 0;  //将下拉表的内容清空
    49        //循环添加选项 
    50        //如果 ,如果节点较多的话可以考虑先声明一个文档片段,然后把选项添加到文档片段
    51        //最后将文档对象附加到下拉表
    52        for(var i=0,j=json.length;i<j;i++){
    53             var option = document.createElement("OPTION");
    54             option.value =json[i].Value;
    55             option.innerHTML = json[i].Text;     
    56             opObj.appendChild(option);            
    57        }
    ;
    58        opObj.selectedIndex = 0 ; //默认选中第一个
    59        //如果其onchange事件存在,那么触发这个事件,用于多级联动
    60        //大家可以注意一下我这里的引用方式opObj["onchange"],效果同 opObj.onchange
    61        if(opObj["onchange"!= null){
    62            opObj.fireEvent("onchange"); 
    63    }

    64    }
    ;
    65    catch(e){
    66        throw e;
    67        //alert(e.description);
    68        return ;
    69    }

    70    ;
    71    
    72}
    ;
    73AutoFill.prototype.callBackError=function (ret,opObj){
    74    alert("Error:\n"+ret);//未实现    
    75}
    ;

    IXBCallbackHandler.cs

     1using System;
     2using System.Collections.Generic;
     3using System.Text;
     4using System.Web.UI.WebControls;
     5
     6namespace Beyondbit.Soft3.WebControl
     7{
     8    public interface IXBCallbackHandler
     9    {
    10        List<ListItem> GetIXBCallBackReslut(ListItem parent,string callItemId) ;
    11    }

    12}

    NetLoad.js

     1 /*
     2@author : xuanye(ilik)
     3@Createdate:2006-12-14
     4@des : xmlHttp请求类
     5*/

     6function NetLoad(smothod,surl,sasync,sOpbackObj,scallback) {
     7    this.xmlObj = this.CreateObjHttp();
     8    this.method=smothod?smothod:"POST";
     9    this.url = surl?surl:this.GetPesentUrl();
    10    this.async=sasync?sasync:true;
    11    this.OpbackObj=sOpbackObj?sOpbackObj:null;
    12    this.contentXMLDom=null ;    
    13    this.callback=scallback?scallback:function(cbobj,opobj) {return;}
    14}

    15NetLoad.prototype.GetPesentUrl = function()
    16{
    17    var __theForm = document.forms[0] ;
    18    if(__theForm &&__theForm.action)
    19    return __theForm.action ;
    20    else
    21    return window.location.href ;
    22}

    23NetLoad.prototype.send = function(context)
    24{  
    25    var netload = this ;    
    26    if(!netload.method||!netload.url||!netload.async) return false;
    27        netload.xmlObj.open (netload.method, netload.url, netload.async);
    28        if(netload.method=="POST") netload.xmlObj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    29        netload.xmlObj.onreadystatechange=function() {
    30            if(netload.xmlObj.readyState==4{
    31                if(netload.xmlObj.status==200{                   
    32                    netload.callback(netload.xmlObj,netload.OpbackObj);
    33                }

    34            }

    35        }

    36        if(netload.method=="POST" && typeof(context) != "undifined" ){     
    37            if(netload.contentXMLDom==null)
    38                netload.contentXMLDom = netload.GetXmlDom();             
    39            netload.contentXMLDom.loadXML(context);
    40            netload.xmlObj.send(netload.contentXMLDom);
    41        }

    42        else {
    43            netload.xmlObj.send(null);
    44        }

    45}

    46NetLoad.prototype.GetXmlDom = function()
    47{
    48      var obj = null;
    49      if (typeof(DOMParser) != "undefined"// Gecko、Mozilla、Firefox
    50        var parser = new DOMParser();
    51        obj = parser.parseFromString(xmlText, "text/xml");
    52      }
     else // IE
    53        try { obj = new ActiveXObject("MSXML2.DOMDocument");} catch (e) { }
    54        if (obj == nulltry { obj = new ActiveXObject("Microsoft.XMLDOM"); } catch (e) { }
    55      }

    56      return obj;
    57}

    58NetLoad.prototype.CreateObjHttp = function()
    59{
    60    var xhttp = null;
    61    if(window.XMLHttpRequest)
    62    //IE7, Mozilla ,Firefox 
    63      xhttp = new XMLHttpRequest();      
    64    }

    65    else if(window.ActiveXObject)
    66    //IE6、IE5
    67      try
    68         xhttp = new ActiveXObject("Msxml2.XMLHTTP");
    69      }
     
    70      catch (e){ ; }      
    71      if( xhttp == null)
    72      {
    73       try {
    74            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    75        }

    76        catch (e){; }   
    77      }
        
    78    }

    79    return xhttp;
    80}

    本来回调使用的是微软本身的ICallBack但是在实现多级关联的时候,即回调中又触发另外一次回调的时候js报错了,大概看了一下,应该是用了全局变量,在第二次回调的时候变量的值又被改变了。循环因子大于索引了。。 代码大部份已经给了详细的注释。。
    汗,忘了讲怎么调用了,
    编译成dll之后,在工具栏拖到页面上即可使用多级联动就拖多个,对应不同的父子关系
    可以在使用的页面或者继承该控件的子控件中实现IXBCallbackHandler接口,

    parent就是触发联动的下拉菜单的选中项的,callItemID就是联动控件的ClientID,在多级联动中可以根据这个判断这个值来判断是哪个回调,然后相应的返回各自的对应数据
    取数据的方法是自己定义的返回一个ListItem的数组即可,因为没有放演示的空间 。。唉

  • 相关阅读:
    自定义动画animate()
    【Java】正则表达式
    【Java】连接数据库SQLServer
    【Java】导入导出TXT文件
    【数据库】SELECT语句
    数据结构与算法系列之目录
    【Java】员工统计
    【Java】生产者消费者模式
    【Java】购物超市
    【Java】导入导出Excel表格
  • 原文地址:https://www.cnblogs.com/xuanye/p/642827.html
Copyright © 2011-2022 走看看