下面是代码:
先是建了一个用户控件Suggest.ascx
前台代码:
下拉提示控件 前台代码
1
<%
@ Control Language="C#" AutoEventWireup="true" CodeFile="Suggest.ascx.cs" Inherits="Suggest" %>
2
3
<style type="text/css">
4
5
.pnlSuggest
6
{
}{
7
border: #000000 1px solid;
8
background-color: #FFFFFF;
9
z-index: 9527;
10
position: absolute;
11
overflow-y: auto;
12
overflow-x: hidden;
13
text-overflow: clip;
14
}
15
16
.pnlSuggest table
17
{
}{
18
width: 100%;
19
}
20
21
.pnlSuggest tr
22
{
}{
23
width: 100%;
24
}
25
26
.trmouseover
27
{
}{
28
width: 100%;
29
background-color: #397CC3;
30
}
31
32
.trmouseover td
33
{
}{
34
text-align: left;
35
overflow: hidden;
36
text-overflow: clip;
37
background-color: #397CC3;
38
}
39
40
.trmouseout
41
{
}{
42
width: 100%;
43
background-color: #FFFFFF;
44
}
45
46
.trmouseout td
47
{
}{
48
text-align: left;
49
overflow: hidden;
50
text-overflow: clip;
51
background-color: #FFFFFF;
52
}
53
54
.txtValues
55
{
}{
56
display: none;
57
}
58
59
.dataSource
60
{
}{
61
display: none;
62
}
63
64
.hiddentd
65
{
}{
66
display: none;
67
}
68
69
.hiddenValues
70
{
}{
71
display: none;
72
}
73
74
</style>
75
76
<script language="javascript" type="text/javascript">
77
78
//为string对象添加一个清除前后空格的属性
79
String.prototype.trim = function()
80

{
81
return this.replace(new RegExp("(^[//s]*)|([//s]*$)", "g"), "");
82
};
83
84
//显示下拉信息
85
function ShowSuggest(objInputText)
86

{
87
objInputText.onkeyup = ControlSuggest;
88
89
objInputText.onblur = RemoveSuggest;
90
91
var oldValue = objInputText.parentElement.getElementsByTagName("h6")[0];
92
93
//对提示框的控制
94
function ControlSuggest()
95
{
96
var ie = (document.all)?true:false;
97
if(ie)
98
{
99
var keycode = event.keyCode;
100
var txtvalues = objInputText.value.trim().split(";");
101
102
if( !CheckSuggest() && txtvalues[txtvalues.length-1] != oldValue.innerText.trim())
103
{
104
CreateSuggest();
105
return ;
106
}
107
108
if(keycode == 32 && txtvalues[txtvalues.length-1] != oldValue.innerText.trim())
109
{
110
CreateSuggest();
111
return ;
112
}
113
114
//按向下创建提示
115
if(!CheckSuggest() && txtvalues[txtvalues.length-1].length !=0 && keycode == 40)
116
{//文本框有内容,提示不存在,向下
117
CreateSuggest();
118
return;
119
}
120
121
//当删除的时候,参量要初始化
122
if(keycode == 8 && txtvalues[txtvalues.length-1].length == 0)
123
{
124
DeleteSuggest();
125
oldValue.innerText = "";
126
return ;
127
}
128
129
if(CheckSuggest())
130
{
131
var inputIndex = document.getElementById("inputIndex");
132
var selectIndex = Number(inputIndex.value);
133
134
//排除上下控制的值操作外,其他任何值改变都要去创建提示框
135
if( selectIndex < 0 && txtvalues[txtvalues.length-1] != oldValue.innerText)
136
{
137
CreateSuggest();
138
return ;
139
}
140
141
if(keycode == 40)
142
{//向下
143
ChangeSelection(false);
144
return ;
145
}
146
147
if(keycode == 38)
148
{//向上
149
ChangeSelection(true);
150
return ;
151
}
152
153
if(keycode == 46 || keycode == 27)
154
{//del
155
DeleteSuggest();
156
oldValue.innerText = "";
157
return ;
158
}
159
160
var panelSuggest = document.getElementById("divSuggestPanel");
161
var tb = panelSuggest.getElementsByTagName("table")[0];
162
163
if(keycode == 13)
164
{//回车
165
if(selectIndex > -1 && txtvalues[txtvalues.length-1] != oldValue.innerText)
166
{
167
CreateSuggest();
168
return ;
169
}
170
RemoveSuggest();
171
return ;
172
}
173
174
}
175
176
if(txtvalues[txtvalues.length-1] != oldValue.innerText)
177
{//当上面的条件都筛选后,只要值发生改变就创建下拉提示
178
CreateSuggest();
179
return ;
180
}
181
}
182
}
183
184
//删除提示前对文本做相关操作
185
function RemoveSuggest()
186
{
187
if(CheckSuggest())
188
{
189
var panelSuggest = document.getElementById("divSuggestPanel");
190
var inputIndex = document.getElementById("inputIndex");
191
192
var txtvalues = objInputText.value.trim().split(";");
193
194
if( CheckActiveElement(panelSuggest) || event.keyCode == 13)
195
{
196
//做个判断,判断当前活动对象 是不是TD,是的话就执行下面的操作,不是的话就不做操作,或者把文本框作为当前活动
197
if(CheckActiveElement(panelSuggest) && document.activeElement.tagName != "TD")
198
{
199
objInputText.focus();
200
return ;
201
}
202
203
//得到选定的值
204
var selectIndex = Number(inputIndex.value);
205
if(selectIndex >= 0)
206
{
207
var tb = panelSuggest.getElementsByTagName("table")[0];
208
txtvalues[txtvalues.length-1] = tb.rows[selectIndex].cells[0].innerText;
209
objInputText.value = GetValues(txtvalues);
210
}
211
}
212
213
document.body.removeChild(inputIndex);
214
document.body.removeChild(panelSuggest);
215
oldValue.innerText = "";
216
}
217
else
218
{
219
return ;
220
}
221
}
222
223
//删除提示的方法,不对文本做任何操作
224
function DeleteSuggest()
225
{
226
if(CheckSuggest())
227
{
228
var panelSuggest = document.getElementById("divSuggestPanel");
229
var inputIndex = document.getElementById("inputIndex");
230
document.body.removeChild(inputIndex);
231
document.body.removeChild(panelSuggest);
232
}
233
}
234
235
//加载提示框
236
function CreateSuggest()
237
{
238
var txtvalues = objInputText.value.trim().split(";");
239
240
//提示框存在,而且文本框值与上次的输入不同时,才进行下面的加载工作
241
if(CheckSuggest())
242
{
243
if( oldValue.innerText.trim() == txtvalues[txtvalues.length-1].trim())
244
{
245
return ;
246
}
247
else
248
{
249
DeleteSuggest();
250
}
251
}
252
253
if(CheckSuggest() && txtvalues[txtvalues.length-1].trim().length ==0)
254
{//提示框存在,但是文本框没有内容,这时删除提示框
255
DeleteSuggest();
256
oldValue.innerText = "";
257
return ;
258
}
259
260
//如果输入为空格,就退出
261
if(txtvalues[txtvalues.length-1].trim().length == 0)
262
{
263
return ;
264
}
265
266
//从数据源中取数据
267
var suggestList = GetSuggestList();
268
269
if(suggestList == null||suggestList.length < 1)
270
{//对传入的数组进行判断,为空或者列表为0就退出
271
DeleteSuggest(); //开始的输入有提示,后面的输入可能没有提示,所以数据源为空时要尝试删除提示
272
oldValue.innerText = "";
273
return ;
274
}
275
276
oldValue.innerText = txtvalues[txtvalues.length-1]; //以上条件都符合,根据数据源来创建数据
277
278
var inputIndex = document.createElement("input"); //用隐藏控件来做索引的保存
279
inputIndex.type = "hidden";
280
inputIndex.id = "inputIndex";
281
inputIndex.value = -1;
282
283
var suggest = ""; //根据数据源来写div提示信息
284
suggest += "<table>";
285
for(var nIndex = 0; nIndex < suggestList.length; nIndex++)
286
{
287
suggest += "<tr onmouseover=/" for(var n=0;n<this.parentElement.rows.length;n++)
{this.parentElement.rows[n].className='trmouseout';};this.className='trmouseover';var inputIndex = document.getElementById('inputIndex');inputIndex.value = this.rowIndex; /" onmouseout=/"this.className='trmouseout';/" >";
288
suggest += suggestList[nIndex];
289
suggest += "</tr>";
290
}
291
suggest += "</table>";
292
293
var panelSuggest = document.createElement("div"); //创建装提示框的容器div
294
295
panelSuggest.id = "divSuggestPanel";
296
panelSuggest.className = "pnlSuggest"; //设置对象的类
297
panelSuggest.style.width = objInputText.clientWidth + "px"; //设置对象的宽度,与文本框宽度相同
298
panelSuggest.style.top = (GetPosition()[0] + objInputText.offsetHeight + 1) + "px";
299
panelSuggest.style.left = GetPosition()[1] + "px";
300
panelSuggest.innerHTML = suggest;
301
302
document.body.appendChild(panelSuggest); //把提示框和索引控件添加进来
303
document.body.appendChild(inputIndex);
304
305
//判断显示条数的多少,多于10条就用滚动条操作
306
if(suggestList.length > 10)
307
{
308
var h = panelSuggest.getElementsByTagName("tr")[1].offsetHeight;
309
panelSuggest.style.height = (h * 10) + "px";
310
panelSuggest.style.width = (objInputText.clientWidth + 20) + "px";
311
}
312
313
}
314
315
//更换选项
316
function ChangeSelection(isup)
317
{
318
319
if(CheckSuggest())
320
{
321
var txtvalues = objInputText.value.trim().split(";");
322
323
var inputIndex = document.getElementById("inputIndex"); //得到索引的值
324
var selectIndex = Number(inputIndex.value);
325
326
var panelSuggest = document.getElementById("divSuggestPanel"); //得到提示框
327
var tb = panelSuggest.getElementsByTagName("table")[0];
328
var maxIndex = tb.rows.length - 1; //提示信息的最大索引
329
330
if(isup)
331
{//向上
332
if(selectIndex >= 0) //索引不能为负
333
{
334
tb.rows[selectIndex].className = "trmouseout";
335
selectIndex--;
336
if(selectIndex >= 0)
337
{
338
tb.rows[selectIndex].className = "trmouseover";
339
}
340
}
341
}
342
else
343
{
344
if(selectIndex < maxIndex) //大于等于最大索引就不做任何操作
345
{
346
if(selectIndex >= 0)
347
{
348
tb.rows[selectIndex].className = "trmouseout";
349
}
350
selectIndex++;
351
tb.rows[selectIndex].className = "trmouseover";
352
}
353
}
354
355
inputIndex.value = selectIndex;
356
//控制滚动条的上下
357
if(selectIndex >= 0)
358
{
359
if(tb.rows[selectIndex].offsetTop < panelSuggest.scrollTop)
360
{
361
panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop;
362
}
363
if(tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight > panelSuggest.scrollTop + panelSuggest.offsetHeight)
364
{
365
panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight - panelSuggest.offsetHeight;
366
}
367
}
368
369
}
370
371
}
372
373
//判断活动对象是否为obj对象的从属对象
374
function CheckActiveElement(obj)
375
{
376
var isAe = false;
377
var objtemp = document.activeElement;
378
while(objtemp != null)
379
{
380
if(objtemp == obj)
381
{
382
isAe = true;
383
break;
384
}
385
objtemp = objtemp.parentElement;
386
}
387
return isAe;
388
}
389
390
//检查提示框是否存在
391
function CheckSuggest()
392
{
393
var panelSuggest = document.getElementById("divSuggestPanel");
394
if(panelSuggest == null)
395
{
396
return false;
397
}
398
else
399
{
400
return true;
401
}
402
}
403
404
//获取文本框的位置
405
function GetPosition()
406
{
407
var top = 0,left = 0;
408
var obj = objInputText;
409
do
410
{
411
top += obj.offsetTop; //距离顶部
412
left += obj.offsetLeft; //距离左边
413
}
414
while (obj = obj.offsetParent);
415
416
var arr = new Array();
417
arr[0] = top;
418
arr[1] = left;
419
return arr;
420
}
421
422
//得到提示数据
423
function GetSuggestList()
424
{
425
var txtvalues = objInputText.value.trim().split(";");
426
var txtfield = txtvalues[txtvalues.length-1];
427
var hiddenvaluefield = objInputText.parentElement.getElementsByTagName("h2")[0].innerText;
428
var showtextfield = objInputText.parentElement.getElementsByTagName("h3")[0].innerText;
429
var procedurename = objInputText.parentElement.getElementsByTagName("h4")[0].innerText;
430
var condition = objInputText.parentElement.getElementsByTagName("h5")[0].innerText;
431
var suggestlist = Suggest.GetSuggestData(txtfield,showtextfield,procedurename,condition).value;
432
return suggestlist;
433
}
434
435
//得到文本框的显示值
436
function GetValues(values)
437
{
438
var txtvalue="";
439
for(var n=0;n<values.length;n++)
440
{
441
if(values[n].trim().length==0)
442
{
443
continue;
444
}
445
txtvalue+=values[n]+";";
446
}
447
return txtvalue;
448
}
449
450
}
451
452
</script>
453
454
<div>
455
<input type="text" runat="server" id="txtInput" name="txtInput" onkeydown="ShowSuggest(this);" style="width: 320px" autocomplete="off" />
456
<h2 id="hneedfield" runat="server" class="hiddenValues"></h2>
457
<h3 id="hshowfield" runat="server" class="hiddenValues"></h3>
458
<h4 id="hprocedurename" runat="server" class="hiddenValues"></h4>
459
<h5 id="hhashvalue" runat="server" class="hiddenValues"></h5>
460
<h6 class="hiddenValues" style="display: none;"></h6>
461
</div>
462

下拉提示控件 后台代码
1
using System;
2
using System.Data;
3
using System.Configuration;
4
using System.Collections;
5
using System.Web;
6
using System.Web.Security;
7
using System.Web.UI;
8
using System.Web.UI.WebControls;
9
using System.Web.UI.WebControls.WebParts;
10
using System.Web.UI.HtmlControls;
11
using System.Collections.Generic;
12
using System.Data.SqlClient;
13
using IIP.Data.SQLHelper;
14
15
/**//// <summary>
16
/// 作者:李宏武
17
/// 时间:2008年7月18号
18
/// 公司:
19
/// 项目:
20
/// 模块:仿google下拉提示的文本输入框控件
21
/// 修改记录:无
22
/// 使用说明:调用该控件,要设置控件的相关属性:
23
/// 显示提示的筛选字段名 TextField
24
/// 查询数据的存储过程名 Procedurename
25
/// 存储过程的各项参数 ProcedureParams(Hashtable类型,key值放参数名,value值为参数值)
26
/// 还可以通过下面的方法,设置域的值:
27
/// List<string> showFields 要下拉提示的相关信息 AddShowFields(string field)方法添加
28
/// 设置好上面的信息后就可以使用了,要得到文本框信息,通过属性Text得到
29
/// 要取得与文本信息相匹配的隐藏信息,也就是与hiddenFields对应的信息,通过属性Values得到
30
/// </summary>
31
public partial class Suggest : System.Web.UI.UserControl
32

{
33
private string textField;
34
35
/**//// <summary>
36
/// 设置要显示提示的筛选字段名
37
/// </summary>
38
public string TextField
39
{
40
set
{ textField = value; }
41
}
42
43
private string valueField;
44
45
/**//// <summary>
46
/// 设置要得到的唯一性标识的字段名
47
/// </summary>
48
public string ValueField
49
{
50
set
{ valueField = value; }
51
}
52
53
private string procedurename;
54
55
/**//// <summary>
56
/// 设置查询数据的存储过程名
57
/// </summary>
58
public string Procedurename
59
{
60
set
{ procedurename = value; }
61
}
62
63
private Hashtable procedureParams = new Hashtable();
64
65
/**//// <summary>
66
/// 设置存储过程的各项参数
67
/// </summary>
68
public Hashtable ProcedureParams
69
{
70
set
{ procedureParams = value; }
71
}
72
73
private List<string> showFields = new List<string>();
74
75
/**//// <summary>
76
/// 添加显示内容的字段
77
/// </summary>
78
/// <param name="field">字段名</param>
79
public void AddShowFields(string field)
80
{
81
showFields.Add(field);
82
}
83
84
/**//// <summary>
85
/// 得到文本框的值
86
/// </summary>
87
public string Text
88
{
89
get
90
{
91
string[] texts = txtInput.Value.Split(new string[]
{ ";" }, StringSplitOptions.None);
92
DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);
93
string txtvalue = "";
94
foreach (string text in texts)
95
{
96
DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0] + " = '" + text + "'");
97
if (drs.Length > 0)
98
{
99
txtvalue += text + ",";
100
}
101
}
102
return txtvalue;
103
}
104
}
105
106
/**//// <summary>
107
/// 得到与文本框值匹配的信息
108
/// </summary>
109
public string Values
110
{
111
get
112
{
113
string[] texts = txtInput.Value.Split(new string[]
{ ";" }, StringSplitOptions.None);
114
DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);
115
string value = "";
116
foreach (string text in texts)
117
{
118
DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0] + " = '" + text + "'");
119
if (drs.Length > 0)
120
{
121
value += drs[0][this.hneedfield.InnerText.Trim()].ToString() + ",";
122
}
123
}
124
return value;
125
}
126
}
127
128
/**//// <summary>
129
/// 得到数据源
130
/// </summary>
131
/// <param name="procedurename">存储过程名</param>
132
/// <param name="condition">存储过程参数</param>
133
/// <returns>查询数据源</returns>
134
private DataTable GetDataSourse(string procedurename, string condition)
135
{
136
//从数据源得到数据
137
string[] keyandvalue = condition.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);
138
139
SqlParameter[] commandparameters;
140
if (keyandvalue.Length == 0)
141
{
142
commandparameters = null;
143
}
144
else
145
{
146
commandparameters = new SqlParameter[keyandvalue.Length];
147
for (int i = 0; i < commandparameters.Length; i++)
148
{
149
string[] tempvalue = keyandvalue[i].Split(new string[]
{ "$h,57,w$" }, StringSplitOptions.None);
150
commandparameters[i] = new SqlParameter(tempvalue[0], SqlDbType.VarChar, 500);
151
commandparameters[i].Value = tempvalue[1];
152
}
153
}
154
155
DataSet ds = SqlHelper.ExecuteDataset(Comm.connectionString, CommandType.StoredProcedure, procedurename, commandparameters);
156
if (ds == null || ds.Tables[0] == null)
157
{
158
return null;
159
}
160
else
161
{
162
return ds.Tables[0];
163
}
164
}
165
166
/**//// <summary>
167
/// 根据输入内容,得到数据
168
/// </summary>
169
/// <param name="txtfield">显示文本</param>
170
/// <param name="showtextfield">下拉提示的相关字段</param>
171
/// <param name="procedurename">存储过程名</param>
172
/// <param name="condition">存储过程参数</param>
173
[Ajax.AjaxMethod]
174
public string[] GetSuggestData(string txtfield, string showtextfield, string procedurename, string condition)
175
{
176
177
//数据的要显示字段和要相关得到数值的字段
178
string[] shows = showtextfield.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);
179
180
//数据的筛选
181
DataTable dt = GetDataSourse(procedurename, condition);
182
if (dt == null)
183
{
184
return null;
185
}
186
DataRow[] drs = dt.Select(shows[0] + " like '%" + txtfield + "%'");
187
if (drs.Length == 0)
188
{
189
return null;
190
}
191
192
//将数据做为显示流
193
List<string> fields = new List<string>();
194
195
for (int j = 0; j < shows.Length; j++)
196
{
197
fields.Add(shows[j]);
198
}
199
200
string[] tbs = new string[drs.Length];
201
int count = 0;
202
foreach (DataRow dr in drs)
203
{
204
foreach (string item in fields)
205
{
206
tbs[count] += "<td>" + dr[item].ToString() + "</td>";
207
}
208
count++;
209
}
210
return tbs;
211
}
212
213
/**//// <summary>
214
/// 页面的相关信息的保存
215
/// </summary>
216
private void BindValue()
217
{
218
//页面中加上与文本输入相关的有下拉提示的字段
219
this.hshowfield.InnerText = this.textField;
220
int i = 0;
221
foreach (string item in showFields)
222
{
223
this.hshowfield.InnerText += "$h,w$";
224
this.hshowfield.InnerText += item;
225
i++;
226
}
227
228
//页面中加上查询数据源的存储过程
229
this.hprocedurename.InnerText = this.procedurename;
230
231
//页面中加上与存储过程匹配的参数
232
this.hhashvalue.InnerText = "";
233
if (procedureParams != null && procedureParams.Count > 0)
234
{
235
i = 0;
236
foreach (DictionaryEntry temp in procedureParams)
237
{
238
if (i != 0)
239
{
240
this.hhashvalue.InnerText += "$h,w$";
241
}
242
this.hhashvalue.InnerText += temp.Key.ToString() + "$h,57,w$" + temp.Value.ToString();
243
i++;
244
}
245
}
246
247
//唯一标识的字段名
248
this.hneedfield.InnerText = this.valueField;
249
}
250
251
protected void Page_Load(object sender, EventArgs e)
252
{
253
Ajax.Utility.RegisterTypeForAjax(typeof(SearchText));
254
if (!IsPostBack)
255
{
256
BindValue();
257
}
258
}
259
}
260
先是建了一个用户控件Suggest.ascx
前台代码:
1

<%
@ Control Language="C#" AutoEventWireup="true" CodeFile="Suggest.ascx.cs" Inherits="Suggest" %>2

3

<style type="text/css">
4

5
.pnlSuggest6

{
}{7
border: #000000 1px solid;8
background-color: #FFFFFF;9
z-index: 9527;10
position: absolute;11
overflow-y: auto;12
overflow-x: hidden;13
text-overflow: clip;14
}15

16
.pnlSuggest table17

{
}{18
width: 100%;19
}20

21
.pnlSuggest tr22

{
}{23
width: 100%;24
}25

26
.trmouseover27

{
}{28
width: 100%;29
background-color: #397CC3;30
}31

32
.trmouseover td33

{
}{34
text-align: left;35
overflow: hidden;36
text-overflow: clip;37
background-color: #397CC3;38
}39

40
.trmouseout41

{
}{42
width: 100%;43
background-color: #FFFFFF;44
}45

46
.trmouseout td47

{
}{48
text-align: left;49
overflow: hidden;50
text-overflow: clip;51
background-color: #FFFFFF;52
}53

54
.txtValues55

{
}{56
display: none;57
}58

59
.dataSource60

{
}{61
display: none;62
}63

64
.hiddentd65

{
}{66
display: none;67
}68

69
.hiddenValues70

{
}{71
display: none;72
}73

74
</style>75

76

<script language="javascript" type="text/javascript">
77

78
//为string对象添加一个清除前后空格的属性79
String.prototype.trim = function()80


{81
return this.replace(new RegExp("(^[//s]*)|([//s]*$)", "g"), "");82
};83

84
//显示下拉信息85
function ShowSuggest(objInputText)86


{87
objInputText.onkeyup = ControlSuggest;88
89
objInputText.onblur = RemoveSuggest;90
91
var oldValue = objInputText.parentElement.getElementsByTagName("h6")[0];92
93
//对提示框的控制94
function ControlSuggest()95

{96
var ie = (document.all)?true:false;97
if(ie)98

{99
var keycode = event.keyCode;100
var txtvalues = objInputText.value.trim().split(";");101
102
if( !CheckSuggest() && txtvalues[txtvalues.length-1] != oldValue.innerText.trim())103

{104
CreateSuggest();105
return ;106
}107
108
if(keycode == 32 && txtvalues[txtvalues.length-1] != oldValue.innerText.trim())109

{110
CreateSuggest();111
return ;112
}113
114
//按向下创建提示115
if(!CheckSuggest() && txtvalues[txtvalues.length-1].length !=0 && keycode == 40)116

{//文本框有内容,提示不存在,向下117
CreateSuggest();118
return;119
}120
121
//当删除的时候,参量要初始化122
if(keycode == 8 && txtvalues[txtvalues.length-1].length == 0)123

{124
DeleteSuggest();125
oldValue.innerText = "";126
return ;127
}128
129
if(CheckSuggest())130

{131
var inputIndex = document.getElementById("inputIndex");132
var selectIndex = Number(inputIndex.value);133
134
//排除上下控制的值操作外,其他任何值改变都要去创建提示框135
if( selectIndex < 0 && txtvalues[txtvalues.length-1] != oldValue.innerText)136

{137
CreateSuggest();138
return ;139
}140
141
if(keycode == 40)142

{//向下143
ChangeSelection(false);144
return ;145
}146
147
if(keycode == 38)148

{//向上149
ChangeSelection(true);150
return ;151
}152
153
if(keycode == 46 || keycode == 27)154

{//del155
DeleteSuggest();156
oldValue.innerText = "";157
return ;158
}159
160
var panelSuggest = document.getElementById("divSuggestPanel");161
var tb = panelSuggest.getElementsByTagName("table")[0];162

163
if(keycode == 13)164

{//回车165
if(selectIndex > -1 && txtvalues[txtvalues.length-1] != oldValue.innerText)166

{167
CreateSuggest();168
return ;169
}170
RemoveSuggest();171
return ;172
}173
174
}175
176
if(txtvalues[txtvalues.length-1] != oldValue.innerText)177

{//当上面的条件都筛选后,只要值发生改变就创建下拉提示178
CreateSuggest();179
return ;180
}181
}182
}183
184
//删除提示前对文本做相关操作185
function RemoveSuggest()186

{187
if(CheckSuggest())188

{189
var panelSuggest = document.getElementById("divSuggestPanel");190
var inputIndex = document.getElementById("inputIndex");191
192
var txtvalues = objInputText.value.trim().split(";");193
194
if( CheckActiveElement(panelSuggest) || event.keyCode == 13)195

{196
//做个判断,判断当前活动对象 是不是TD,是的话就执行下面的操作,不是的话就不做操作,或者把文本框作为当前活动197
if(CheckActiveElement(panelSuggest) && document.activeElement.tagName != "TD")198

{199
objInputText.focus();200
return ;201
}202
203
//得到选定的值204
var selectIndex = Number(inputIndex.value);205
if(selectIndex >= 0)206

{207
var tb = panelSuggest.getElementsByTagName("table")[0];208
txtvalues[txtvalues.length-1] = tb.rows[selectIndex].cells[0].innerText;209
objInputText.value = GetValues(txtvalues);210
}211
}212
213
document.body.removeChild(inputIndex);214
document.body.removeChild(panelSuggest);215
oldValue.innerText = "";216
}217
else218

{219
return ;220
}221
}222
223
//删除提示的方法,不对文本做任何操作224
function DeleteSuggest()225

{226
if(CheckSuggest())227

{228
var panelSuggest = document.getElementById("divSuggestPanel");229
var inputIndex = document.getElementById("inputIndex");230
document.body.removeChild(inputIndex);231
document.body.removeChild(panelSuggest);232
}233
}234
235
//加载提示框236
function CreateSuggest()237

{238
var txtvalues = objInputText.value.trim().split(";");239
240
//提示框存在,而且文本框值与上次的输入不同时,才进行下面的加载工作241
if(CheckSuggest())242

{243
if( oldValue.innerText.trim() == txtvalues[txtvalues.length-1].trim())244

{245
return ;246
}247
else248

{249
DeleteSuggest();250
}251
}252
253
if(CheckSuggest() && txtvalues[txtvalues.length-1].trim().length ==0)254

{//提示框存在,但是文本框没有内容,这时删除提示框255
DeleteSuggest();256
oldValue.innerText = "";257
return ;258
}259
260
//如果输入为空格,就退出261
if(txtvalues[txtvalues.length-1].trim().length == 0)262

{263
return ;264
} 265
266
//从数据源中取数据267
var suggestList = GetSuggestList();268
269
if(suggestList == null||suggestList.length < 1)270

{//对传入的数组进行判断,为空或者列表为0就退出271
DeleteSuggest(); //开始的输入有提示,后面的输入可能没有提示,所以数据源为空时要尝试删除提示272
oldValue.innerText = "";273
return ;274
}275
276
oldValue.innerText = txtvalues[txtvalues.length-1]; //以上条件都符合,根据数据源来创建数据277
278
var inputIndex = document.createElement("input"); //用隐藏控件来做索引的保存279
inputIndex.type = "hidden";280
inputIndex.id = "inputIndex";281
inputIndex.value = -1;282
283
var suggest = ""; //根据数据源来写div提示信息284
suggest += "<table>";285
for(var nIndex = 0; nIndex < suggestList.length; nIndex++)286

{287

suggest += "<tr onmouseover=/" for(var n=0;n<this.parentElement.rows.length;n++)
{this.parentElement.rows[n].className='trmouseout';};this.className='trmouseover';var inputIndex = document.getElementById('inputIndex');inputIndex.value = this.rowIndex; /" onmouseout=/"this.className='trmouseout';/" >";288
suggest += suggestList[nIndex];289
suggest += "</tr>";290
}291
suggest += "</table>";292
293
var panelSuggest = document.createElement("div"); //创建装提示框的容器div294
295
panelSuggest.id = "divSuggestPanel";296
panelSuggest.className = "pnlSuggest"; //设置对象的类297
panelSuggest.style.width = objInputText.clientWidth + "px"; //设置对象的宽度,与文本框宽度相同298
panelSuggest.style.top = (GetPosition()[0] + objInputText.offsetHeight + 1) + "px";299
panelSuggest.style.left = GetPosition()[1] + "px";300
panelSuggest.innerHTML = suggest;301
302
document.body.appendChild(panelSuggest); //把提示框和索引控件添加进来 303
document.body.appendChild(inputIndex);304
305
//判断显示条数的多少,多于10条就用滚动条操作306
if(suggestList.length > 10)307

{308
var h = panelSuggest.getElementsByTagName("tr")[1].offsetHeight;309
panelSuggest.style.height = (h * 10) + "px";310
panelSuggest.style.width = (objInputText.clientWidth + 20) + "px";311
}312
313
}314
315
//更换选项316
function ChangeSelection(isup)317

{318

319
if(CheckSuggest())320

{321
var txtvalues = objInputText.value.trim().split(";");322
323
var inputIndex = document.getElementById("inputIndex"); //得到索引的值324
var selectIndex = Number(inputIndex.value);325
326
var panelSuggest = document.getElementById("divSuggestPanel"); //得到提示框327
var tb = panelSuggest.getElementsByTagName("table")[0]; 328
var maxIndex = tb.rows.length - 1; //提示信息的最大索引329
330
if(isup)331

{//向上332
if(selectIndex >= 0) //索引不能为负333

{334
tb.rows[selectIndex].className = "trmouseout";335
selectIndex--;336
if(selectIndex >= 0)337

{338
tb.rows[selectIndex].className = "trmouseover";339
}340
}341
}342
else343

{344
if(selectIndex < maxIndex) //大于等于最大索引就不做任何操作345

{346
if(selectIndex >= 0)347

{348
tb.rows[selectIndex].className = "trmouseout";349
}350
selectIndex++;351
tb.rows[selectIndex].className = "trmouseover";352
}353
}354
355
inputIndex.value = selectIndex;356
//控制滚动条的上下357
if(selectIndex >= 0)358

{359
if(tb.rows[selectIndex].offsetTop < panelSuggest.scrollTop)360

{361
panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop;362
}363
if(tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight > panelSuggest.scrollTop + panelSuggest.offsetHeight)364

{365
panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight - panelSuggest.offsetHeight;366
}367
}368
369
}370
371
}372
373
//判断活动对象是否为obj对象的从属对象374
function CheckActiveElement(obj)375

{376
var isAe = false;377
var objtemp = document.activeElement;378
while(objtemp != null)379

{380
if(objtemp == obj)381

{382
isAe = true;383
break;384
}385
objtemp = objtemp.parentElement;386
}387
return isAe;388
}389
390
//检查提示框是否存在391
function CheckSuggest()392

{393
var panelSuggest = document.getElementById("divSuggestPanel");394
if(panelSuggest == null)395

{396
return false;397
}398
else399

{400
return true;401
}402
}403
404
//获取文本框的位置405
function GetPosition()406

{407
var top = 0,left = 0;408
var obj = objInputText;409
do 410

{411
top += obj.offsetTop; //距离顶部412
left += obj.offsetLeft; //距离左边413
}414
while (obj = obj.offsetParent);415
416
var arr = new Array();417
arr[0] = top;418
arr[1] = left;419
return arr; 420
}421
422
//得到提示数据423
function GetSuggestList()424

{425
var txtvalues = objInputText.value.trim().split(";");426
var txtfield = txtvalues[txtvalues.length-1];427
var hiddenvaluefield = objInputText.parentElement.getElementsByTagName("h2")[0].innerText;428
var showtextfield = objInputText.parentElement.getElementsByTagName("h3")[0].innerText;429
var procedurename = objInputText.parentElement.getElementsByTagName("h4")[0].innerText;430
var condition = objInputText.parentElement.getElementsByTagName("h5")[0].innerText;431
var suggestlist = Suggest.GetSuggestData(txtfield,showtextfield,procedurename,condition).value;432
return suggestlist;433
}434
435
//得到文本框的显示值436
function GetValues(values)437

{438
var txtvalue="";439
for(var n=0;n<values.length;n++)440

{441
if(values[n].trim().length==0)442

{443
continue;444
}445
txtvalue+=values[n]+";";446
}447
return txtvalue;448
}449
450
}451

452
</script>453

454
<div>455
<input type="text" runat="server" id="txtInput" name="txtInput" onkeydown="ShowSuggest(this);" style="width: 320px" autocomplete="off" />456
<h2 id="hneedfield" runat="server" class="hiddenValues"></h2>457
<h3 id="hshowfield" runat="server" class="hiddenValues"></h3>458
<h4 id="hprocedurename" runat="server" class="hiddenValues"></h4>459
<h5 id="hhashvalue" runat="server" class="hiddenValues"></h5>460
<h6 class="hiddenValues" style="display: none;"></h6>461
</div>462

后台代码:
1
using System;2
using System.Data;3
using System.Configuration;4
using System.Collections;5
using System.Web;6
using System.Web.Security;7
using System.Web.UI;8
using System.Web.UI.WebControls;9
using System.Web.UI.WebControls.WebParts;10
using System.Web.UI.HtmlControls;11
using System.Collections.Generic;12
using System.Data.SqlClient;13
using IIP.Data.SQLHelper;14

15

/**//// <summary>16
/// 作者:李宏武17
/// 时间:2008年7月18号18
/// 公司:19
/// 项目:20
/// 模块:仿google下拉提示的文本输入框控件21
/// 修改记录:无22
/// 使用说明:调用该控件,要设置控件的相关属性:23
/// 显示提示的筛选字段名 TextField24
/// 查询数据的存储过程名 Procedurename25
/// 存储过程的各项参数 ProcedureParams(Hashtable类型,key值放参数名,value值为参数值)26
/// 还可以通过下面的方法,设置域的值:27
/// List<string> showFields 要下拉提示的相关信息 AddShowFields(string field)方法添加28
/// 设置好上面的信息后就可以使用了,要得到文本框信息,通过属性Text得到29
/// 要取得与文本信息相匹配的隐藏信息,也就是与hiddenFields对应的信息,通过属性Values得到30
/// </summary>31
public partial class Suggest : System.Web.UI.UserControl32


{33
private string textField;34

35

/**//// <summary>36
/// 设置要显示提示的筛选字段名37
/// </summary>38
public string TextField39

{40

set
{ textField = value; }41
}42

43
private string valueField;44

45

/**//// <summary>46
/// 设置要得到的唯一性标识的字段名47
/// </summary>48
public string ValueField49

{50

set
{ valueField = value; }51
}52

53
private string procedurename;54

55

/**//// <summary>56
/// 设置查询数据的存储过程名57
/// </summary>58
public string Procedurename59

{60

set
{ procedurename = value; }61
}62

63
private Hashtable procedureParams = new Hashtable();64

65

/**//// <summary>66
/// 设置存储过程的各项参数67
/// </summary>68
public Hashtable ProcedureParams69

{70

set
{ procedureParams = value; }71
}72

73
private List<string> showFields = new List<string>();74

75

/**//// <summary>76
/// 添加显示内容的字段77
/// </summary>78
/// <param name="field">字段名</param>79
public void AddShowFields(string field)80

{81
showFields.Add(field);82
}83

84

/**//// <summary>85
/// 得到文本框的值86
/// </summary>87
public string Text88

{89
get 90

{91

string[] texts = txtInput.Value.Split(new string[]
{ ";" }, StringSplitOptions.None);92
DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);93
string txtvalue = "";94
foreach (string text in texts)95

{96

DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0] + " = '" + text + "'");97
if (drs.Length > 0)98

{99
txtvalue += text + ",";100
}101
}102
return txtvalue;103
}104
}105

106

/**//// <summary>107
/// 得到与文本框值匹配的信息108
/// </summary>109
public string Values110

{111
get112

{113

string[] texts = txtInput.Value.Split(new string[]
{ ";" }, StringSplitOptions.None);114
DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);115
string value = "";116
foreach (string text in texts)117

{118

DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0] + " = '" + text + "'");119
if (drs.Length > 0)120

{121
value += drs[0][this.hneedfield.InnerText.Trim()].ToString() + ",";122
}123
}124
return value;125
}126
}127

128

/**//// <summary>129
/// 得到数据源130
/// </summary>131
/// <param name="procedurename">存储过程名</param>132
/// <param name="condition">存储过程参数</param>133
/// <returns>查询数据源</returns>134
private DataTable GetDataSourse(string procedurename, string condition)135

{136
//从数据源得到数据137

string[] keyandvalue = condition.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);138

139
SqlParameter[] commandparameters;140
if (keyandvalue.Length == 0)141

{142
commandparameters = null;143
}144
else145

{146
commandparameters = new SqlParameter[keyandvalue.Length];147
for (int i = 0; i < commandparameters.Length; i++)148

{149

string[] tempvalue = keyandvalue[i].Split(new string[]
{ "$h,57,w$" }, StringSplitOptions.None);150
commandparameters[i] = new SqlParameter(tempvalue[0], SqlDbType.VarChar, 500);151
commandparameters[i].Value = tempvalue[1];152
}153
}154

155
DataSet ds = SqlHelper.ExecuteDataset(Comm.connectionString, CommandType.StoredProcedure, procedurename, commandparameters);156
if (ds == null || ds.Tables[0] == null)157

{158
return null;159
}160
else161

{162
return ds.Tables[0];163
}164
}165

166

/**//// <summary>167
/// 根据输入内容,得到数据168
/// </summary>169
/// <param name="txtfield">显示文本</param>170
/// <param name="showtextfield">下拉提示的相关字段</param>171
/// <param name="procedurename">存储过程名</param>172
/// <param name="condition">存储过程参数</param>173
[Ajax.AjaxMethod]174
public string[] GetSuggestData(string txtfield, string showtextfield, string procedurename, string condition)175

{176
177
//数据的要显示字段和要相关得到数值的字段178

string[] shows = showtextfield.Split(new string[]
{ "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);179

180
//数据的筛选181
DataTable dt = GetDataSourse(procedurename, condition);182
if (dt == null)183

{184
return null;185
}186
DataRow[] drs = dt.Select(shows[0] + " like '%" + txtfield + "%'");187
if (drs.Length == 0)188

{189
return null;190
}191

192
//将数据做为显示流193
List<string> fields = new List<string>();194

195
for (int j = 0; j < shows.Length; j++)196

{197
fields.Add(shows[j]);198
}199

200
string[] tbs = new string[drs.Length];201
int count = 0;202
foreach (DataRow dr in drs)203

{204
foreach (string item in fields)205

{206
tbs[count] += "<td>" + dr[item].ToString() + "</td>";207
}208
count++;209
}210
return tbs;211
}212

213

/**//// <summary>214
/// 页面的相关信息的保存215
/// </summary>216
private void BindValue()217

{218
//页面中加上与文本输入相关的有下拉提示的字段219
this.hshowfield.InnerText = this.textField;220
int i = 0;221
foreach (string item in showFields)222

{223
this.hshowfield.InnerText += "$h,w$";224
this.hshowfield.InnerText += item;225
i++;226
}227

228
//页面中加上查询数据源的存储过程229
this.hprocedurename.InnerText = this.procedurename;230

231
//页面中加上与存储过程匹配的参数232
this.hhashvalue.InnerText = "";233
if (procedureParams != null && procedureParams.Count > 0)234

{235
i = 0;236
foreach (DictionaryEntry temp in procedureParams)237

{238
if (i != 0)239

{240
this.hhashvalue.InnerText += "$h,w$";241
}242
this.hhashvalue.InnerText += temp.Key.ToString() + "$h,57,w$" + temp.Value.ToString();243
i++;244
}245
}246

247
//唯一标识的字段名248
this.hneedfield.InnerText = this.valueField;249
}250

251
protected void Page_Load(object sender, EventArgs e)252

{253
Ajax.Utility.RegisterTypeForAjax(typeof(SearchText));254
if (!IsPostBack)255

{256
BindValue();257
}258
}259
}260

然后在aspx页面就可以拖这个控件来用,不过在其page_load方法中,要对控件的两个控件进行设置,不然是不会有提示框弹出的,因为数据源都没有。呵呵
效果是仿google做的

本文介绍了一种仿照Google风格的下拉提示文本输入框控件的实现方法。该控件可通过设置相关属性来自定义显示提示的字段、查询数据的存储过程等,并提供了文本框值及匹配信息的获取方式。
211

被折叠的 条评论
为什么被折叠?



