效果图:

目标:选择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向服务器请求相应的数据
1
function choose(ddl)
2
{
3
sendRequest_Item('http://localhost:83/WebService/Comment.asmx','GetItemList','Get','iCategoryID='+ddl.value+'');
4
}


1
function 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
}
19
function 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呗。


1
function 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,大功告成!
感受:
本来以为弄这么个小东西顶多一上午时间就够了,没想到中间出现了不少问题,一个个解决后,发现竟然用了我一整天(包括晚上啊)的时间。唉,看来做什么事都不能大意啊。另外,大家有什么更好的方法,欢迎一起研究研究,呵呵!