网上有不少实现自动完成的asp.net控件,也有不少基于jquery实现的插件。
现在我采用jquery插件,在asp.net2.0环境下实现了重写Textbox控件来实现自动完成功能,并提供下载!
该控件在设计时绑定自动完成内容有6种方式:
MyTestBox控件测试用例:
1.直接对下拉匹配项进行赋值(集合):
输入a-d既有提示,匹配集合内容在设计器中设置,如下图:

2.DataTable进行赋值(集合):
事先为DataTable进行赋值,然后在后台Load页面进行绑定,代码如下:
protected
void
Page_Load(
object
sender, EventArgs e)

...
{ //(一). 测试绑定DataTable 通过测试
DataTable dt = CreateDataTable();
MyTestBox2.DataSource = dt;
MyTestBox2.DataTextField = "Text"; //指定绑定的列
MyTestBox2.DataBind();
}
3.DataSet进行赋值(集合):
protected
void
Page_Load(
object
sender, EventArgs e)

...
{//(二). 测试绑定DataSet 通过测试
DataSet ds = CreateDataSet();
MyTestBox3.DataSource = ds;
MyTestBox3.DataMember = ds.Tables[0].TableName;//如果不声明此句,会默认取DataSet中的第一个表
MyTestBox3.DataTextField = "Text";
MyTestBox3.DataBind();
}
4.绑定ArrayList进行赋值(集合):
5.绑定强类型集合进行赋值(集合):
//
(三). 测试绑定ArrayList 需要自定义Item类以及相关项 通过测试
ArrayList al
=
new
ArrayList();
al.Add(
new
Item(
"
aaArrayList
"
));
al.Add(
new
Item(
"
abArrayList
"
));
al.Add(
new
Item(
"
baArrayList
"
));
al.Add(
new
Item(
"
bbArrayList
"
));
MyTestBox4.DataSource
=
al;
MyTestBox4.DataBind();
//
(四). 绑定强类型集合类型 需要自定义强类型 测试通过
temList itemList
=
new
ItemList();
itemList.Add(
new
Item(
"
aaItemList
"
));
itemList.Add(
new
Item(
"
abItemList
"
));
itemList.Add(
new
Item(
"
baItemList
"
));
itemList.Add(
new
Item(
"
bbItemList
"
));
MyTestBox5.DataSource
=
itemList;
MyTestBox5.DataBind();
6.绑定XML类型集合进行赋值(集合):
/**/
////(五). 绑定XML 未测试
string
strDataFile
=
Path.Combine(Request.PhysicalApplicationPath,
"
XMLFile.xml
"
);
string
strSchemaFile
=
Path.Combine(Request.PhysicalApplicationPath,
"
XMLSchema.xsd
"
);
MyTestBox1.XMLDataFile
=
strDataFile;
MyTestBox1.XMLSchemaFile
=
strSchemaFile;
MyTestBox控件主要代码说明:
该控件继承TextBox控件,通过在页面中加载javascript资源文件和函数以及css样式来进行自动完成。为了开发绑定数据方便,特提供了多种绑定数据内容方式。
程序主要包含以下文件:
主类:MyTestBox.cs
类型转换类:StringArrayConverter.cs
资源文件:jquery_pack.js等js函数以及css样式
MyTestBox.cs内容如下:
using
System;
using
System.Text;
using
System.Data;
using
System.Drawing;
using
System.ComponentModel;
using
System.Configuration;
using
System.Collections;
using
System.Collections.Generic;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.Design;
using
System.Web.UI.WebControls;
using
System.Xml;
using
System.Xml.Schema;
using
System.Xml.Serialization;

[assembly: WebResource(MyComponent.MyTestBox.JSbgiframe_min,
"
text/javascript
"
)]
[assembly: WebResource(MyComponent.MyTestBox.JSautocomplete,
"
text/javascript
"
)]
[assembly: WebResource(MyComponent.MyTestBox.JSdimensions,
"
text/javascript
"
)]
[assembly: WebResource(MyComponent.MyTestBox.JSjquery_pack,
"
text/javascript
"
)]
[assembly: WebResource(MyComponent.MyTestBox.CSSautocomplete,
"
text/css
"
)]

namespace
MyComponent

...
{
public class MyTestBox : TextBox

...{

Members 资源#region Members 资源
public const string JSjquery_pack = "MyComponent.res.jquery_pack.js";
public const string JSbgiframe_min = "MyComponent.res.jquery_bgiframe_min.js";
public const string JSdimensions = "MyComponent.res.dimensions.js";
public const string JSautocomplete = "MyComponent.res.jquery_autocomplete.js";
public const string CSSautocomplete = "MyComponent.res.jquery_autocomplete.css";
#endregion


Members 参数#region Members 参数
private bool blnMultiTypeDataSource = false;
private object _dataSource = null;

[TypeConverter(typeof(MyComponent.TypeConvert.StringArrayConverter))]
public virtual string[] Items

...{

get ...{ return ViewState["ItemsStr"] != null ? (string[])ViewState["ItemsStr"] : null; }

set ...{ ViewState["ItemsStr"] = value; }
}

[
Bindable(true),
Category("Data"),
DefaultValue(null),
Description("获取或设置数据源"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual object DataSource

...{
get

...{
return _dataSource;
}
set

...{
if ((value == null) || (value is IListSource) || (value is IEnumerable))

...{
_dataSource = value;
}
else

...{
throw new ArgumentException();
}
}
}

/**//// <summary>
/// 控件显示的文本数据成员
/// </summary>
[
Bindable(true),
Category("Data"),
DefaultValue(null)
]
public string DataTextField

...{
get

...{
String s = (String)ViewState["DataTextField"];
return ((s == null) ? String.Empty : s);
}
set

...{
ViewState["DataTextField"] = value;
}
}
[
Category("Data"),
DefaultValue(""),
Description("获取或者设置绑定的数据成员.")
]
public virtual string DataMember

...{
get

...{
string s = (string)ViewState["DataMember"];
return (s == null) ? String.Empty : s;
}
set

...{
ViewState["DataMember"] = value;
}
}
[
Bindable(true),
Category("Data"),
DefaultValue(null),
Description("获取或设置XML文件路径"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual string XMLDataFile

...{
get

...{
string s = (string)ViewState["XMLDataFile"];
return (s == null) ? String.Empty : s;
}
set

...{
ViewState["XMLDataFile"] = value;
}
}

[
Bindable(true),
Category("Data"),
DefaultValue(null),
Description("获取或设置XML模式文件路径"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual string XMLSchemaFile

...{
get

...{
string s = (string)ViewState["XMLSchemaFile"];
return (s == null) ? String.Empty : s;
}
set

...{
ViewState["XMLSchemaFile"] = value;
}
}

//获取数据源,将数据源中的数据都转换为IEnumerable类型
protected virtual IEnumerable GetDataSource()

...{
if (_dataSource == null)

...{
return null;
}
IEnumerable resolvedDataSource = _dataSource as IEnumerable;
if (resolvedDataSource != null)

...{
return resolvedDataSource; //强类型集合 ArrayListd
}

this.blnMultiTypeDataSource = true; //表示为Datatable

IListSource listSource = _dataSource as IListSource;
if (listSource != null)

...{
IList memberList = listSource.GetList();

if (listSource.ContainsListCollection == false)

...{
return (IEnumerable)memberList; //DataTable
}
ITypedList typedMemberList = memberList as ITypedList;
if (typedMemberList != null)

...{
PropertyDescriptorCollection propDescs = typedMemberList.GetItemProperties(new PropertyDescriptor[0]);
PropertyDescriptor memberProperty = null;

if ((propDescs != null) && (propDescs.Count != 0))

...{
string dataMember = DataMember;

if (dataMember.Length == 0)

...{
memberProperty = propDescs[0];
}
else

...{
memberProperty = propDescs.Find(dataMember, true);
}

if (memberProperty != null)

...{
object listRow = memberList[0];
object list = memberProperty.GetValue(listRow);

if (list is IEnumerable)

...{
return (IEnumerable)list; //DataSet
}
}
throw new Exception("未能找到有效的DataMember.");
}

throw new Exception("数据源中不包含任何数据对象.");
}
}
return null;
}

private PropertyDescriptor[] GetColumnPropertyDescriptors(object dataItem)

...{
ArrayList props = new ArrayList();
PropertyDescriptorCollection propDescs = TypeDescriptor.GetProperties(dataItem);
foreach (PropertyDescriptor pd in propDescs)

...{
Type propType = pd.PropertyType;
TypeConverter converter = TypeDescriptor.GetConverter(propType);
if ((converter != null) && converter.CanConvertTo(typeof(string)))

...{
props.Add(pd);
}
}
PropertyDescriptor[] columns = new PropertyDescriptor[props.Count];
props.CopyTo(columns, 0);
return columns;
}

protected virtual string CreateControlTBValues()

...{
StringBuilder strvalues = new StringBuilder();
IEnumerable dataSource = null;
dataSource = GetDataSource();
int columnCount;
if (dataSource != null)

...{
PropertyDescriptor[] properties = null;
foreach (object dataItem in dataSource)

...{
properties = GetColumnPropertyDescriptors(dataItem);
columnCount = properties.Length;
string tvalue = "";
if (blnMultiTypeDataSource == false)

...{
PropertyDescriptor pdImage = properties[0];
object TextBoxValue = pdImage.GetValue(dataItem);
tvalue = (string)pdImage.Converter.ConvertTo(TextBoxValue, typeof(string));
}
else

...{
string text = "";
for (int j = 0; j < columnCount; j++)

...{
PropertyDescriptor pd = properties[j];
object objValue = pd.GetValue(dataItem);
string strValue = (string)pd.Converter.ConvertTo(objValue, typeof(string));
if (String.Compare(pd.Name, this.DataTextField, true) == 0)

...{
text = strValue;
}
}
tvalue = text;
}

strvalues.Append(""" + tvalue + "",");
}
}

if (this.XMLDataFile + String.Empty != String.Empty)

...{
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
NameTable nt = new NameTable();
string link = nt.Add("link");
settings.NameTable = nt;

//验证
settings.Schemas.Add(null, XmlReader.Create(this.XMLSchemaFile));
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler);

//序列化工厂类
XmlSerializerFactory factory = new XmlSerializerFactory();

using (XmlReader reader = XmlReader.Create(this.XMLDataFile, settings))

...{
while (reader.Read())

...{
if (reader.NodeType == XmlNodeType.Element && String.Compare(link, reader.LocalName, true) == 0)

...{
XmlSerializer xs = factory.CreateSerializer(typeof(MyComponent.xml.Link));
MyComponent.xml.Link l = (MyComponent.xml.Link)xs.Deserialize(reader.ReadSubtree());
strvalues.Append(""" + l.Text + "",");
}
}
}
}

return strvalues.ToString();
}

/**//// <summary>
/// 当设置数据源时, 要验证XML文件格式是否正确; 当格式不正确时,此方法用来处理当XML文件格式不正确时,要进行的操作
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void settings_ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs e)

...{
throw new Exception("数据文件: " + this.XMLDataFile + " 格式不正确! [" + e.Message + "]");
}

//public override void DataBind()
//{
// base.OnDataBinding(EventArgs.Empty);
//}
#endregion


protected override void OnPreRender(EventArgs e)

...{
SetMETA();
SetJS();
SetlinkCss();
Scriptfunc();
base.OnPreRender(e);
}

protected override void Render(HtmlTextWriter writer)

...{
base.Render(writer);
}

/**////<summary>
///在<head></head>标签中设置META属性
///</summary>
private void SetMETA()

...{
string strMETA = "<META http-equiv=Content-Type content="text/html; charset=gb2312">";
string METAKey = "gb2312";
if (this.Page.Header.FindControl(METAKey) != null)
return;

Literal ltlMETA = new Literal();
ltlMETA.ID = METAKey;
ltlMETA.Text = strMETA;

this.Parent.Page.Header.Controls.Add(ltlMETA);
}

/**////<summary>
///在<head></head>标签中添加js链接
///</summary>
private void SetJS()

...{
string JSjquery_packstr = string.Format(" <script language="javascript" type="text/javascript" src="{0}"></script> _fcksavedurl=""{0}"></script>" ", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), JSjquery_pack));
string JSbgiframe_minstr = string.Format("<script language="javascript" type="text/javascript" src="{0}"></script> _fcksavedurl=""{0}"></script>" ", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), JSbgiframe_min));
string JSdimensionsstr = string.Format("<script language="javascript" type="text/javascript" src="{0}"></script> _fcksavedurl=""{0}"></script>" ", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), JSdimensions));
string JSautocompletestr = string.Format("<script language="javascript" type="text/javascript" src="{0}"></script> _fcksavedurl=""{0}"></script>" ", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), JSautocomplete));

//jquery-1.1.2.pack.js
string JSjquery_packkey = "JSjquery_packstr";
if (this.Page.Header.FindControl(JSjquery_packkey) != null)
return;
Literal JSjquery_packltl = new Literal();
JSjquery_packltl = new Literal();
JSjquery_packltl.ID = JSjquery_packkey;
JSjquery_packltl.Text = JSjquery_packstr;
this.Parent.Page.Header.Controls.Add(JSjquery_packltl);

//jquery.bgiframe.min.js
string JSbgiframe_minkey = "JSbgiframe_minstr";
if (this.Page.Header.FindControl(JSbgiframe_minkey) != null)
return;
Literal JSbgiframe_minltl = new Literal();
JSbgiframe_minltl = new Literal();
JSbgiframe_minltl.ID = JSbgiframe_minkey;
JSbgiframe_minltl.Text = JSbgiframe_minstr;
this.Parent.Page.Header.Controls.Add(JSbgiframe_minltl);

//dimensions.js
string JSdimensionskey = "JSdimensionsstr";
if (this.Page.Header.FindControl(JSdimensionskey) != null)
return;
Literal JSdimensionsltl = new Literal();
JSdimensionsltl = new Literal();
JSdimensionsltl.ID = JSdimensionskey;
JSdimensionsltl.Text = JSdimensionsstr;
this.Parent.Page.Header.Controls.Add(JSdimensionsltl);

//jquery.autocomplete.js
string JSautocompletekey = "JSautocompletestr";
if (this.Page.Header.FindControl(JSautocompletekey) != null)
return;
Literal JSautocompleteltl = new Literal();
JSautocompleteltl = new Literal();
JSautocompleteltl.ID = JSautocompletekey;
JSautocompleteltl.Text = JSautocompletestr;
this.Parent.Page.Header.Controls.Add(JSautocompleteltl);
}

/**////<summary>
///在<head></head>标签中添加css链接
///</summary>
private void SetlinkCss()

...{
string strCssLink = string.Format("<link href="{0}" rel="stylesheet" type="text/css" /> ", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), CSSautocomplete));
string cssKey = "autocomplete_css";
if (this.Page.Header.FindControl(cssKey) != null)
return;

Literal ltlCss = new Literal();
ltlCss.ID = cssKey;
ltlCss.Text = strCssLink;

this.Parent.Page.Header.Controls.Add(ltlCss);
}

private void Scriptfunc()

...{
StringBuilder itemvalues = new StringBuilder();
string datasc = CreateControlTBValues();
if (datasc != string.Empty)

...{
itemvalues.Append(datasc);
}
if (this.Items != null)

...{
foreach (string str in this.Items)

...{
itemvalues.Append(""" + str + """);
if (str != this.Items[this.Items.Length - 1])
itemvalues.Append(",");
}
}
else

...{
itemvalues.Append("""");
}
StringBuilder startupscript = new StringBuilder();
startupscript.AppendLine("<script language="javascript" type="text/javascript">");
startupscript.AppendLine("var " + this.ClientID + "_autovalues = [");
//startupscript.AppendLine(Items.ToString());
startupscript.AppendLine(itemvalues.ToString());
//startupscript.Append(""aaaa","aabb","bbbb","bbbcc"");
startupscript.AppendLine("];");
startupscript.AppendLine("$().ready(function() {$("#" + this.ClientID + "").autocomplete(" + this.ClientID + "_autovalues);});");
startupscript.AppendLine("</script>");
//Page.RegisterStartupScript(this.ClientID + "loading", startupscript.ToString());

string DataLoadingkey = this.ClientID + "DataLoading";
if (this.Page.Header.FindControl(DataLoadingkey) != null)
return;
Literal DataLoadingltl = new Literal();
DataLoadingltl = new Literal();
DataLoadingltl.ID = DataLoadingkey;
DataLoadingltl.Text = startupscript.ToString();
this.Parent.Page.Header.Controls.Add(DataLoadingltl);
}
}
}