效果图:
目标:选择DropDownList,左侧ListBox从服务器端获取对应项。点击Button,对左、右侧ListBox进行操作。
最后在服务器端获取右侧ListBox的值
过程:
1、首先是给DropDownList弄个数据源,实际开发中一般都是从数据库去。我这演示方便就随便new 了个DataTable。
1private void DllBindData()
2 {
3 DataTable table = new DataTable("MyCategory");
4 DataColumn column;
5 DataRow row;
6 column = new DataColumn();
7 column.DataType = System.Type.GetType("System.Int32");
8 column.ColumnName = "iSysCode";
9 table.Columns.Add(column);
10
11 column = new DataColumn();
12 column.DataType = System.Type.GetType("System.String");
13 column.ColumnName = "cName";
14 table.Columns.Add(column);
15
16 row = table.NewRow();
17 row["iSysCode"] = 1;
18 row["cName"] = "编程语言";
19 table.Rows.Add(row);
20
21 row = table.NewRow();
22 row["iSysCode"] = 2;
23 row["cName"] = "编程工具";
24 table.Rows.Add(row);
25
26 row = table.NewRow();
27 row["iSysCode"] = 3;
28 row["cName"] = "数据库";
29 table.Rows.Add(row);
30
31 ddlCategory.DataSource = table.DefaultView;
32 ddlCategory.DataValueField = "iSysCode";
33 ddlCategory.DataTextField = "cName";
34 ddlCategory.DataBind();
35 }
2、有了数据,下面就开始操作了。
在DropDownList的客户端事件onchange中添加choose函数,choose中调用sendRequest_Item向服务器请求相应的数据
1function choose(ddl)
2 {
3 sendRequest_Item('http://localhost:83/WebService/Comment.asmx','GetItemList','Get','iCategoryID='+ddl.value+'');
4 }
1function sendRequest_Item(url, Method, HttpMethod,params) //发送请求
2{
3 url += "/" + Method;
4 if (!HttpMethod)
5 {
6 HttpMethod = "GET";
7 }
8 req = getXMLRequester(); //建立组件
9 if (req)
10 {
11 req.onreadystatechange = processReqChange_Item;//调用[设定]进程监视函数
12 req.open(HttpMethod, url, false);
13 req.setRequestHeader("Host", "localhost");//发布时要更正 Host
14 req.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//一定要加上charset,否则有乱码
15 req.setRequestHeader("Content-Length",params.length);
16 req.send(params); //发送数据参数
17 }
18}
19function processReqChange_Item()
20{
21 // 监视数据传递。
22 if (req.readyState == 4)
23 {
24 if (req.status == 200)
25 {
26 xmlResponse_Item(); // connect OK 执行输出函数out()
27 }
28 else
29 { //抛出错误
30 alert("无法正常连接服务器,错误:\n" +
31 req.statusText+":"+req.status);
32 }
33 }
34}
3、服务器端用了个WebService返回数据
1[WebMethod]
2 public string GetItemList(int iCategoryID)
3 {
4 string sbResult = "<Items>";
5
6 DataTable dt = GetItemTable(iCategoryID);
7 foreach (DataRow dr in dt.Rows)
8 {
9 sbResult += string.Format("<Item value='{0}'>{1}</Item>", dr["iSysCode"].ToString(), dr["cName"].ToString());
10 }
11 sbResult+=("</Items>");
12 return sbResult;
13
14 }
15 //模拟数据库数据源表
16 public DataTable GetItemTable(int iCategoryID)
17 {
18 DataTable table = new DataTable("MyTable");
19 DataColumn column;
20 DataRow row;
21 column = new DataColumn();
22 column.DataType = System.Type.GetType("System.Int32");
23 column.ColumnName = "iSysCode";
24 table.Columns.Add(column);
25
26 column = new DataColumn();
27 column.DataType = System.Type.GetType("System.String");
28 column.ColumnName = "cName";
29 table.Columns.Add(column);
30
31 switch (iCategoryID)
32 {
33 case 1:
34 row = table.NewRow();
35 row["iSysCode"] = 11;
36 row["cName"] = "C#";
37 table.Rows.Add(row);
38
39 row = table.NewRow();
40 row["iSysCode"] = 12;
41 row["cName"] = "Java";
42 table.Rows.Add(row);
43
44 row = table.NewRow();
45 row["iSysCode"] = 13;
46 row["cName"] = "C++";
47 table.Rows.Add(row);
48
49 row = table.NewRow();
50 row["iSysCode"] = 14;
51 row["cName"] = "VB";
52 table.Rows.Add(row);
53
54 break;
55 case 2:
56 row = table.NewRow();
57 row["iSysCode"] = 21;
58 row["cName"] = "Visual Studio";
59 table.Rows.Add(row);
60
61 row = table.NewRow();
62 row["iSysCode"] = 22;
63 row["cName"] = "JBuilder";
64 table.Rows.Add(row);
65
66 row = table.NewRow();
67 row["iSysCode"] = 23;
68 row["cName"] = "Eclipse";
69 table.Rows.Add(row);
70 break;
71 case 3:
72 row = table.NewRow();
73 row["iSysCode"] = 31;
74 row["cName"] = "MySQL";
75 table.Rows.Add(row);
76
77 row = table.NewRow();
78 row["iSysCode"] = 32;
79 row["cName"] = "SQL Server";
80 table.Rows.Add(row);
81
82 row = table.NewRow();
83 row["iSysCode"] = 33;
84 row["cName"] = "Oracle";
85 table.Rows.Add(row);
86
87 row = table.NewRow();
88 row["iSysCode"] = 34;
89 row["cName"] = "DB2";
90 table.Rows.Add(row);
91 break;
92 default:
93 row = table.NewRow();
94 row["iSysCode"] = 11;
95 row["cName"] = "C#";
96 table.Rows.Add(row);
97
98 row = table.NewRow();
99 row["iSysCode"] = 12;
100 row["cName"] = "Java";
101 table.Rows.Add(row);
102
103 row = table.NewRow();
104 row["iSysCode"] = 13;
105 row["cName"] = "C++";
106 table.Rows.Add(row);
107
108 row = table.NewRow();
109 row["iSysCode"] = 14;
110 row["cName"] = "VB";
111 table.Rows.Add(row);
112 break;
113 }
114 return table;
115 }
4、分析操作返回的数据(XML格式)这个是关键,在这花了我好长一段时间:用xmlDoc.getElementsByTagName("Item")方法得到的options,长度length总是为0,但确实是有数据返回;用responseText可以正确取出数据。在网上搜了半天也没找到一个适当的解决方法。郁闷n久之后,找到了问题所在,原来是数据被Encode了。这好办,咱就给他DeEncode呗。
1function xmlResponse_Item() //输出函数【Success】
2{
3 var xmlDoc = new ActiveXObject("MSXML2.DOMDocument.3.0");
4 xmlDoc.async=false;
5 xmlDoc.validateOnParse=false;
6 xmlDoc.loadXML(html(req.responseText));//从服务器端传回的数据 HTML元素被Encode 所以在这用 html 函数反编码
7
8 var lbItem = document.getElementById("lbItem");
9 lbItem.options.length=0;//清空列表框
10
11 var options=xmlDoc.getElementsByTagName("Item");
12
13 for (var i = 0;i<options.length;i++)
14 {
15 lbItem.add(new Option(options[i].text,options[i].getAttribute("value")));
16 }
17}
5、这样一来,DropDownList就可以和左侧的ListBox实现联动了。接下来是如何操作它了。这里我只写了最上面两个按钮的点击实现,大家可以根据自己的需要实现其他的两个。看一下JS代码:
1//移动项
2 function move(type)
3 {
4 var lbItem=document.getElementById("lbItem");//左侧列表
5 var lbResult=document.getElementById("lbResult");//右侧列表
6 if(type=="right")//单项右移
7 {
8 var selIndex=lbItem.selectedIndex;//取出选中项索引
9 if(lbItem.selectedIndex==-1)//没有选择
10 selIndex=0;//没有选择,设为第一项
11 //1.取出选中项内容,移除当前List项
12 var text=lbItem.options[selIndex].text;
13 var value=lbItem.options[selIndex].value;
14
15 if(IsExist(lbResult,text)==true)
16 return;
17 lbItem.remove(selIndex);
18 //2.增加目标List
19 var option=new Option(text,value,true,true);
20 lbResult.add(option);
21 }
22 if(type=="rightAll")//右移左侧所有项
23 {
24 //lbResult.options.length=0;//清空目标List
25 for(var i=0;i<lbItem.length;i++)
26 {
27 var text=lbItem.options[i].text;
28 var value=lbItem.options[i].value;
29 if(IsExist(lbResult,text)==false)//只有目标List没有的才添加
30 {
31 lbResult.add(new Option(text,value,true,true));
32 }
33 }
34
35 lbItem.options.length=0;//清空所操作的List
36 }
37 }
38 //所选项是否在指定列表框 已经存在
39 function IsExist(item,text)
40 {
41 var result=false;
42 for(var i=0;i<item.length;i++)
43 {
44 if(item.options[i].text==text)
45 {
46 result=true;
47 }
48 }
49 return result;
50 }
6、进行到这里,右侧的ListBox已经有了结果项了。剩下的是如何在服务器端获取这部分数据。Test了几下表明用Request.Form这种根本无法直接获取到所需数据。那只好转个弯,先将数据放在hiddenField里,然后在服务器端方法里取出来。OK,大功告成!
感受:
本来以为弄这么个小东西顶多一上午时间就够了,没想到中间出现了不少问题,一个个解决后,发现竟然用了我一整天(包括晚上啊)的时间。唉,看来做什么事都不能大意啊。另外,大家有什么更好的方法,欢迎一起研究研究,呵呵!