当前位置:首页 --> 技术原创 --> 正文

无限级Select联动(图)

2008-9-6 21:13:00 来源:原创 浏览次数: 评论数: 字号:[ ]
      在前一篇“无刷新SELECT联动”中曾经实现过Select联动。但是在那里提供的代码可用性不是很强,并且存在Bug,复用性也不好。因此在这里对代码进行进一步的封装,封装后的代码包含以下功能:
  1、无刷新加载数据
  2、无限级联动
  3、友好的设计时支持
  4、根据ID路径自动加载
  5、Select选择状态往返保持

SortDropDownList.cs

 using System;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Laodeng.Common.DataDictionary.UI
{
    public class SortDropDownListDesigner : System.Web.UI.Design.ControlDesigner
    {
        public override string GetDesignTimeHtml()
        {
            SortDropDownList list = (SortDropDownList)Component;
            return string.Format(@"<SELECT><OPTION value={1} selected>{0}</OPTION></SELECT>", list.DefaultText, list.DefaultValue);
        }
    }
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:SortDropDownList runat=server>")]
    [Designer(typeof(SortDropDownListDesigner))]   
    public class SortDropDownList : WebControl
    {
        #region 属性列表
        private string _LoadPage = "/LoadSort.aspx";
        /// 
        /// 加载数据的页面地址
        /// 
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("/LoadSort.aspx")]
        [Localizable(true)]
        public string LoadPage
        {
            get
            {
                return _LoadPage;
            }
            set
            {
                _LoadPage = value;
            }
        }
        private string _QueryStringKey = "t";
        /// 
        /// 用于传递查询参数的Key
        /// 
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("t")]
        [Localizable(true)]
        public string QueryStringKey
        {
            get
            {
                return _QueryStringKey;
            }
            set
            {
                _QueryStringKey = value;
            }
        }
        private Boolean _IsAutoLoad = true;
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Boolean IsAutoLoad
        {
            get
            {
                return _IsAutoLoad;
            }
            set
            {
                _IsAutoLoad = value;
            }
        }
        private Boolean _IsAutoSelect = true;
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Boolean IsAutoSelect
        {
            get
            {
                return _IsAutoSelect;
            }
            set
            {
                _IsAutoSelect = value;
            }
        }
        private Int32 _Timespace = 100;
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Int32 Timespace
        {
            get
            {
                return _Timespace;
            }
            set
            {
                _Timespace = value;
            }
        }
        private String _DefaultText = "== 请选择 ==";
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String DefaultText
        {
            get
            {
                return _DefaultText;
            }
            set
            {
                _DefaultText = value;
            }
        }
        private String _DefaultValue = "[none]";
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String DefaultValue
        {
            get
            {
                return _DefaultValue;
            }
            set
            {
                _DefaultValue = value;
            }
        }
        private string _SuperID;
        /// 
        /// 当前初始加载的记录
        /// 
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string SuperID
        {
            get
            {
                return _SuperID;
            }
            set
            {
                _SuperID = value;
            }
        }
        private string _SelectedPath;
        /// 
        /// 自动选择的目录路径
        /// 
        [Bindable(false)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String SelectedPath
        {
            get
            {
                if (String.IsNullOrEmpty(Page.Request.Form[ID]))
                {
                    return _SelectedPath;
                }
                else
                {
                    string sp = Page.Request.Form[ID];
                    sp = sp.Replace(DefaultValue, "").Trim(',');
                    return sp;
                }
            }
            set
            {
                _SelectedPath = value;
            }
        }
        private String _SelectedLastValue;
        /// 
        /// 当前选择的最后一个值
        /// 
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        [Browsable(false)]
        public String SelectedLastValue
        {
            get
            {
                if (_SelectedLastValue == null)
                {
                    if (String.IsNullOrEmpty(SelectedPath))
                    {
                        _SelectedLastValue = string.Empty;
                    }
                    else
                    {
                        string[] selectedIds = SelectedPath.Split(',');
                        _SelectedLastValue = selectedIds[selectedIds.Length - 1];
                    }
                }
                return _SelectedLastValue;
            }
        }
        #endregion
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            try
            {
                Page.ClientScript.RegisterClientScriptResource(GetType(), "Laodeng.Common.DataDictionary.UI.sortdropdownlist.js");
            }
            catch { }
        }
        protected override void RenderContents(HtmlTextWriter output)
        {
            try
            {
                output.AddAttribute("id", ID);
                output.RenderBeginTag(HtmlTextWriterTag.Div);
                output.RenderEndTag();
                output.WriteLine("");
            }
            catch { }
        } 
        #region 创建公共脚本
        /// 
        /// 创建公共脚本
        /// 
        /// 
        public String BuildScript()
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine(String.Format("isAutoLoad = {0};", IsAutoLoad.ToString().ToLower()));
            builder.AppendLine(String.Format("isAutoSelect = {0};", IsAutoSelect.ToString().ToLower()));
            builder.AppendLine(String.Format("space = {0};", this.Timespace));
            builder.AppendLine(String.Format("defaultText = \"{0}\";", DefaultText));
            builder.AppendLine(String.Format("defaultValue = \"{0}\";", DefaultValue));
            builder.AppendLine(String.Format("loadPage = \"{0}\";", LoadPage));
            builder.AppendLine(String.Format("queryStringKey = \"{0}\";", QueryStringKey));
            return builder.ToString();
        }
        #endregion
    }
}
 

sortdropdownlist.js

//是否自动加载子数据
var isAutoLoad = true;
//是否自动选择记录项
var isAutoSelect = true;
//数据缓存
var cacheData = new Array();
//自动加载子数据的间隔
var space = 100;
//默认项的文本
var defaultText = "== 请选择 ==";
//默认项的值
var defaultValue = "[none]";
//数据加载地址
var loadPage = "/LoadData.aspx";
//用于传递查询参数的Key
var queryStringKey = "t";
function createItem(divId){
    var newItem = document.createElement("SELECT");
    newItem.name = divId;
    return newItem;
}
function removeChild(divBody, currentItem){
    var watingBox = document.getElementById("watingBox");
    if( watingBox != null ){
        divBody.removeChild(watingBox);
    }
    if( divBody.childNodes.length > 0 ){
        for( var i = divBody.childNodes.length - 1; i > 0; i-- ){
            if( divBody.childNodes[i] != currentItem ){
                divBody.removeChild(divBody.childNodes[i]);
            } else {
                break;
            }
        }
    }
}
function addDefaultOption(currentItem){
    if( defaultText == "" ) return;
    
    var newOption = new Option();
    newOption.value = defaultValue;
    newOption.text = defaultText;
    currentItem.options.add(newOption);
}
function appendSort(currentItem, /*typeId, */data, divId, dValue){
    var divBody = currentItem == null ? document.getElementById(divId) : currentItem.parentNode;//document.getElementById("divBody");
    var newItem = createItem(divId);
   
    removeChild(divBody, currentItem);
    
    if( data.length == 0 ) return;
    
    var newOption = null;
    
    addDefaultOption(newItem);
    
    var selectedValue = null;
    for( var i = 0; i < data.length; i++ ){
        newOption = new Option();
        newOption.value = data[i].id;
        newOption.text = data[i].name;
        newItem.options.add(newOption);
        
        if( data[i].isDefault == "True" && isAutoSelect ){                
            selectedValue = newOption.value;
        }
    }
    if( dValue != null && dValue != "" ){
        var index = dValue.indexOf(",");
        if( index > -1 ){
            selectedValue = dValue.substring(0, index);
            dValue = dValue.substring(index + 1, dValue.length);
        } else {
            selectedValue = dValue;
            dValue = "";
        }
    }
    
    //newItem.setAttribute("typeId", typeId);
    divBody.appendChild( newItem );
    
    if( selectedValue != null ){
        newItem.value = selectedValue;
        
        if( isAutoLoad ){
            setTimeout(function(){
                item_onchange(newItem, /*typeId,*/ selectedValue, divId, dValue);
            }, space);
        }
    }
    
    newItem.onchange = function(){
        item_onchange(this, /*this.getAttribute("typeId"), */this.value, divId, null);
    };
}
function showWatingBox(div){
    var divBody = div;
    var watingBox = document.getElementById("watingBox");
    if( watingBox == null ){
        watingBox = document.createElement("SPAN");
        watingBox.id = "watingBox";
        watingBox.innerHTML = "加载中...";
        divBody.appendChild(watingBox);
    }
}
function item_onchange(element, /*typeId,*/ superId, divId, dValue){
    if( superId != defaultValue ){
        if( cacheData[superId] == null ){
            //var tid = typeId;
            var url = loadPage + "?"+ queryStringKey +"="+ superId +/*"&tid="+ typeId +"&type=short*/ "&r=" + Math.random();
            sendRequest(url, null, "GET", function(){
                var ready = req.readyState;
                var dataScript = null;
                if( ready == 4 ){
                    dataScript = req.responseText;
                    
                    eval( dataScript );
                    
                    cacheData[superId] = data;
         
                    appendSort(element, /*tid, */data, divId, dValue);
                } else {                        
                    showWatingBox( element == null ? document.getElementById(divId) : element.parentNode );
                }
            });
        } else {
            appendSort(element, /*typeId, */cacheData[superId], divId, dValue);
        }
    } else {
        removeChild(element.parentNode, element);
    }
    if( element != null ){
        window.focus();
    }
}
function getXMLHttpRequest(){
    var request = null;
    if( window.XMLHttpRequest){
        request = new XMLHttpRequest();
    } else if( typeof(ActiveXObject) != "undefined" ){
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return request;
}
var req;
function sendRequest(url, params, httpMethod, method){
    if( !httpMethod ){
        httpMethod = "GET";
    }
    
    req = getXMLHttpRequest();
    if( req ){
        req.onreadystatechange = method;
        req.open(httpMethod, url, true);
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        req.send(params);
    }
}
 
上面两个文件构成了联动控件的主要内容,由于需要加载层次数据,所以没有把加载部分的功能也封装起来,只是提示了下面几个属性由用户提供加载的功能:
  LoadPage     //负责加载数据的页面
  QueryStringKey  //用于传递查询参数的Key
  SuperID     //代表当前控件初始加载的数据值
 
 
  LoadPage页面的定义如下:
  1、输出的是Javascript脚本
  2、输入的数据保存在一个名为data的Array中。
  3、data中保存的数据是一个Object,分别有name, id, isDefault属性,isDefault用于默认选择。
  如下一个示例:
  String parentId = Request.QueryString["sid"];
  if (parentId == null) parentId = "";
  Area area = new Area("D:\\XingZhengQu.db");
  DataTable dt = area.GetChild(parentId);
  StringBuilder builder = new StringBuilder();
  builder.AppendLine("var data = new Array();");
  if (dt != null && dt.Rows.Count > 0 )
  {
       foreach (DataRow row in dt.Rows)
       {
            builder.AppendLine(string.Format("data.push({{'name':'{0}','id':'{1}', 'isDefault':'{2}'}});", row["Name"], row["ID"], false));
       }
  }
  Response.Clear();
  Response.Write(builder.ToString());
代码下载
 
 
 
 
?
?