在前一篇“
无刷新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());
代码下载