[分享]新封装的一个实现无刷新连动下拉列表类
近期由于项目需要实现大量的无刷新的连动下拉列表,感觉每个页面都copy一份javascript脚本的方法有点蠢,就产生了封一个通用类的念头,先是我同事myw研究了一个版本(这里特别感谢),感觉他的那个使用的限制太多,就在他的基础上改造了一下,产生了下面的版本,虽然还有一定的使用限制,但总的来说还是比较好用的,具体说说实现及使用方法吧!
1.实现方法:
其实原理很简单,先通过cs脚本初始化javascript脚本,再把javascript脚本通HttpContext.Current.Response.Write写入客户端,当然首先还需对一对DropDownList控件进行简单处理,限定是DropDownList的数据源datasource必须使用datatable,不过可以通过根据需要改造来适应其他类型的数据源;
直接看代码吧,还是比较简单的
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NoRefreshJointDDL
{
/// <summary>
/// 实现两个无刷新联动的DropDownList
/// </summary>
public class CNoFlashDownList:System.Web.UI.Page
{
#region 成员变量
//注册控件
private System.Web.UI.WebControls.DropDownList ddlDriver; //驱动方下拉列表
private System.Web.UI.WebControls.DropDownList ddlDrivener; //从动方下拉列表
//数据源
private DataTable dtDriver; //主动方数据源
private DataTable dtDrivener; //从动方数据源
//驱动部分
private string strDriverValueField = ""; //编码列
private string strDriverTextField = ""; //显示列
private string strDriverRelation = ""; //关系列
//从动部分
private string strDrivenerValueField = ""; //编码列
private string strDrivenerTextField = ""; //显示列
private string strDrivenerRelation = ""; //关系列
#endregion
#region 成员属性
/// <summary>
/// 驱动方关系列
/// </summary>
public string DriverRelation
{
set{strDriverRelation = value;}
}
/// <summary>
/// 从动方关系列
/// </summary>
public string DrivenerRelation
{
set{strDrivenerRelation = value;}
}
#endregion
#region 构造函数
public CNoFlashDownList()
{}
#endregion
#region 实现初始化下拉列表框
//得到下拉列表选定值所在数据源行的行号
private int GetSelectRowID(DropDownList ddl)
{
string strValueFiled = ddl.DataValueField;
string strSelectValue = ddl.SelectedValue.ToString();
DataView dv = new DataView((DataTable)(ddl.DataSource));
dv.Sort = strValueFiled;
return dv.Find(strSelectValue);
}
/// <summary>
/// 注册下拉列表,添加客户端脚本
/// </summary>
/// <param name="driver">驱动方下拉列表</param>
/// <param name="drivener">从动方下拉列表</param>
public void RegisterDropDownList(DropDownList driver,DropDownList drivener)
{
//取得准备数据
ddlDriver = driver;
ddlDrivener = drivener;
strDriverTextField = ddlDriver.DataTextField;
strDriverValueField = ddlDriver.DataValueField;
strDrivenerTextField = ddlDrivener.DataTextField;
strDrivenerValueField = ddlDrivener.DataValueField;
dtDriver = (DataTable)(ddlDriver.DataSource);
dtDrivener = (DataTable)(ddlDrivener.DataSource);
//获取选定值,并过滤从动下拉列表的数据
int iIndex = GetSelectRowID(ddlDriver);
DataRow drFilter = dtDriver.Rows[iIndex];
string strRelate = drFilter[strDriverRelation].ToString().Trim();
DataView dv = new DataView(dtDrivener);
dv.RowFilter = strDriverRelation + "='"+strRelate+"'";
ddlDrivener.Items.Clear();
ddlDrivener.DataSource = dv;
ddlDrivener.DataTextField = strDrivenerTextField;
ddlDrivener.DataValueField = strDrivenerValueField;
ddlDrivener.DataBind();
//加入客户端脚本-初始化部分
string CilentScript = @" <script language=""javascript"">
var countDriver;
var countDrivener;
countDriver=0;
countDrivener=0;
ArrayDriver = new Array();
ArrayDrivener = new Array();";
//初始化数组值,并加入客户端脚本
DataRow drDriver = null;
for(int i = 0;i <dtDriver.Rows.Count ;i++)
{
drDriver = dtDriver.Rows[i];
CilentScript += String.Format("ArrayDriver[countDriver++] = new Array(\"{0}\",\"{1}\",\"{2}\");\n", drDriver[strDriverValueField].ToString(),drDriver[strDriverTextField].ToString(), drDriver[strDriverRelation].ToString());
}
DataRow drDrivener = null;
for(int i = 0;i <dtDrivener.Rows.Count ;i++)
{
drDrivener = dtDrivener.Rows[i];
CilentScript += String.Format("ArrayDrivener[countDrivener++] = new Array(\"{0}\",\"{1}\",\"{2}\");\n", drDrivener[strDrivenerValueField].ToString(),drDrivener[strDrivenerTextField].ToString(), drDrivener[strDrivenerRelation].ToString());
}
//注册驱动下拉列表的项改变事件
string ddlDriverID = ddlDriver.ID.ToString().Trim();
string ddlDrivenerID = ddlDrivener.ID.ToString().Trim();
ddlDriver.Attributes["onchange"] = "javascript:changedownlist(document.Form1," + ddlDriverID + "," + ddlDrivenerID + ");";
//加入客户端脚本-连动部分
CilentScript += @"
function changedownlist(myfrm,Driver,Drivener)
{
var SelectedBigId,i,j,SelectDataType;
for (i= Drivener.options.length-1;i>=0 ;--i)
{
Drivener.options[i] = null;
}
SelectedBigId = Driver.options[Driver.selectedIndex].value;
for (i=0;i<ArrayDriver.length;i++)
{
if (SelectedBigId == ArrayDriver[i][0])
{
SelectDataType = ArrayDriver[i][2];
break;
}
}
j = 0;
for (i=0 ;i< ArrayDrivener.length ;i++)
{
if (SelectDataType == ArrayDrivener[i][2])
{
Drivener.options[j] = new Option(ArrayDrivener[i][1],ArrayDrivener[i][0]);
++j;
}
}
}
</script>";
//将脚本写入客户端
HttpContext.Current.Response.Write(CilentScript);
}
#endregion
}
}
2.使用方法,附测试源码:
首先是取一对DropDownList控件的数据源,并绑定它们
接着当然是实例化类CNoFlashDownList了,如果用的多可以考虑封成静态的
然后是指定它们各自用于连动的关系列,这里暴露的两个属性DriverRelation和DrivenerRelation
uc.DriverRelation = "DataType";
uc.DrivenerRelation = "DataType";
最后是调用RegisterDropDownList方法注册控件了
测试的代码
protected System.Web.UI.WebControls.DropDownList ddlDriver;
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
DataTable dtType = new DataTable();
dtType.Columns.Add("TypeCode");
dtType.Columns.Add("TypeName");
dtType.Columns.Add("DataType");
DataTable dtValue = new DataTable("MyTable");
dtValue.Columns.Add("ValueCode");
dtValue.Columns.Add("ValueName");
dtValue.Columns.Add("DataType");
DataRow Dr = dtType.NewRow();
Dr["TypeCode"] = "AllMoney";
Dr["TypeName"] = "应发工资";
Dr["DataType"] = "Num";
dtType.Rows.Add(Dr);
DataRow Dr1 = dtType.NewRow();
Dr1["TypeCode"] = "Uid";
Dr1["TypeName"] = "身份证号码";
Dr1["DataType"] = "Char";
dtType.Rows.Add(Dr1);
DataRow Dr2 = dtType.NewRow();
Dr2["TypeCode"] = "Worker";
Dr2["TypeName"] = "行政职务";
Dr2["DataType"] = "Meg";
dtType.Rows.Add(Dr2);
//开始添加第二个表中的内容
DataRow Dr3 = dtValue.NewRow();
Dr3["ValueCode"] = "=";
Dr3["ValueName"] = "等于";
Dr3["DataType"] = "Num";
dtValue.Rows.Add(Dr3);
DataRow Dr4 = dtValue.NewRow();
Dr4["ValueCode"] = "<>";
Dr4["ValueName"] = "不等于";
Dr4["DataType"] = "Char";
dtValue.Rows.Add(Dr4);
DataRow Dr5 = dtValue.NewRow();
Dr5["ValueCode"] = "like";
Dr5["ValueName"] = "相似";
Dr5["DataType"] = "Char";
dtValue.Rows.Add(Dr5);
DataRow Dr6 = dtValue.NewRow();
Dr6["ValueCode"] = ">";
Dr6["ValueName"] = "大于";
Dr6["DataType"] = "Num";
dtValue.Rows.Add(Dr6);
DataRow Dr7 = dtValue.NewRow();
Dr7["ValueCode"] = "=";
Dr7["ValueName"] = "不等于";
Dr7["DataType"] = "Meg";
dtValue.Rows.Add(Dr7);
DataRow Dr8 = dtValue.NewRow();
Dr8["ValueCode"] = "=";
Dr8["ValueName"] = "等于";
Dr8["DataType"] = "Meg";
dtValue.Rows.Add(Dr8);
CNoFlashDownList uc = new CNoFlashDownList();
ddlDriver.DataSource = dtType;
ddlDriver.DataTextField = "TypeName";
ddlDriver.DataValueField = "TypeCode";
ddlDriver.DataBind();
ddlDriver.SelectedIndex = 2;
ddlDrivener.DataSource = dtValue;
ddlDrivener.DataTextField ="ValueName";
ddlDrivener.DataValueField = "ValueCode";
ddlDrivener.DataBind();
uc.DriverRelation = "DataType";
uc.DrivenerRelation = "DataType";
uc.RegisterDropDownList(ddlDriver,ddlDrivener);
}
}
3.存在的问题
上面的实现在一个页面只有一对连动的DropDownList控件时完全满足需求,但是如果出现并注册多对时就会产生紊乱了,后来想到重载RegisterDropDownList方法,加一个唯一区别的对标识,重复写段带区别的脚本到客户端,但是还是感觉有点土,因为会重复出现一些类似的脚本,违背了xp编程原则;
希望有兴趣的同仁,对上面的实现,以及我提出的问题提点意见和解决方案,先谢谢了……
下载:NoRefreshJointDDL.rar
[分享]新封装的一个实现无刷新连动下拉列表类(最新版本)