自动完成功能AutoCompleteTextBox
最近封装的AutoCompleteTextBox。我们知道,ASP.NET本身的TextBox也是支持一定的AutoComplete功能的,但是那是依赖浏览器实现的,并不能指定自定义的AutoComplete候选项。本文列举的AutoCompleteTextBox则弥补了这个缺憾。只需设置AutoCompleteTextBox.AutoCompleteData属性,传递一个string[],就能使TextBox支持自定义候选项了。
AutoComplete逻辑
如果没有匹配当前输入的候选项,则同一般的TextBox;
如果只有一个候选项与当前输入匹配,则自动完成;
如果有超过一个候选项与当前输入匹配,则在textbox中自动完成第一个候选项,并弹出包含所有候选项的弹出框。
实现源码
源码是在VS2005编译的,不过实际上几乎没有使用依赖2.0的语法,在vs2003下经极少修改就同样能编译的。
![保存](http://www.chenjiliang.com/Image/Save.jpg)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace Ilungasoft.Framework.Web.UI.WebControls { [ToolboxData("<{0}:AutoCompleteTextBox runat=server></{0}:AutoCompleteTextBox>")] public class AutoCompleteTextBox : WebControl { #region Private Members private TextBox textBox = new TextBox(); private HtmlGenericControl autoCompleteFrame = new HtmlGenericControl(); private string ToJsStringArray(params string[] strs) { if (strs != null && strs.Length > 0) { StringBuilder sb = new StringBuilder(); sb.Append(" new Array("); foreach (string str in strs) { sb.Append(string.Format("'{0}', ", str.Replace("'", "\\'"))); } return sb.ToString().TrimEnd(',', ' ') ");"; } else { return " new Array;"; } } private string MakeUniqueID(string id) { if (id != null && id.Trim().Length > 0) { return string.Concat(this.UniqueID.Replace("$", "_"), "_", id); } else { return this.UniqueID.Replace("$", "_"); } } #endregion #region Properties [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] public string Text { get { if (Page.IsPostBack) { textBox.Text = Page.Request.Form[MakeUniqueID("textBox")]; } return textBox.Text; } set { textBox.Text = value; } } [Bindable(true)] [Category("Behavior")] [DefaultValue("")] [Localizable(true)] public int MaxLength { get { return textBox.MaxLength; } set { textBox.MaxLength = value; } } [Bindable(true)] [Category("Behavior")] [DefaultValue(false)] [Localizable(true)] public bool ReadOnly { get { return textBox.ReadOnly; } set { textBox.ReadOnly = value; } } public string[] AutoCompleteData { get { string[] s = (string[])ViewState["AutoCompleteData"]; return ((s == null) ? null : s); } set { ViewState["AutoCompleteData"] = value; } } #endregion #region Overriden Members protected override void CreateChildControls() { #region create textBox textBox.ID = MakeUniqueID("textBox"); textBox.AutoCompleteType = AutoCompleteType.Disabled; textBox.Attributes.Add("onkeypress", string.Format("return __DoAutoComplete(event, '{0}')", MakeUniqueID(null))); textBox.Attributes.Add("onblur", string.Format("if (!document.show_{0}) document.getElementById('{1}').style.display = 'none';", MakeUniqueID(null), MakeUniqueID("autoCompleteFrame"))); textBox.Width = Width; #endregion #region create autoCompleteFrame autoCompleteFrame.TagName = "iframe"; autoCompleteFrame.ID = MakeUniqueID("autoCompleteFrame"); autoCompleteFrame.Attributes.Add("style", "display:none; position: absolute; border: ridge 1px"); autoCompleteFrame.Attributes.Add("frameborder", "0"); autoCompleteFrame.Attributes.Add("marginheight", "0"); autoCompleteFrame.Attributes.Add("marginwidth", "2"); autoCompleteFrame.Attributes.Add("scrolling", "auto"); autoCompleteFrame.Attributes.Add("width", Width.ToString()); autoCompleteFrame.Attributes.Add("height", "100px"); autoCompleteFrame.Attributes.Add("src", "javascript:''"); autoCompleteFrame.Attributes.Add("onmouseover", string.Format("document.show_{0} = true;", MakeUniqueID(null))); autoCompleteFrame.Attributes.Add("onmouseout", string.Format("document.show_{0} = false;", MakeUniqueID(null))); #endregion } protected override void OnPreRender(EventArgs e) { #region Register Client Script Block if (!Page.ClientScript.IsClientScriptBlockRegistered("__DoAutoComplete")) { string script = string.Concat( "<script language=\"javascript\" type=\"text/javascript\">\r\n", " var isOpera = navigator.userAgent.indexOf('Opera') > -1;\r\n", " var isIE = navigator.userAgent.indexOf('MSIE') > 1 && !isOpera;\r\n", " var isMoz = navigator.userAgent.indexOf('Mozilla/5.') == 0 && !isOpera;\r\n", "\r\n", " function textboxSelect (oTextbox, iStart, iEnd)\r\n", " {\r\n", " switch(arguments.length) {\r\n", " case 1:\r\n", " oTextbox.select();\r\n", " break;\r\n", "\r\n", " case 2:\r\n", " iEnd = oTextbox.value.length;\r\n", " /* falls through */\r\n", " \r\n", " case 3: \r\n", " if (isIE) {\r\n", " var oRange = oTextbox.createTextRange();\r\n", " oRange.moveStart(\"character\", iStart);\r\n", " oRange.moveEnd(\"character\", -oTextbox.value.length iEnd); \r\n", " oRange.select(); \r\n", " } else if (isMoz){\r\n", " oTextbox.setSelectionRange(iStart, iEnd);\r\n", " } \r\n", " }\r\n", "\r\n", " oTextbox.focus();\r\n", " }\r\n", "\r\n", " function textboxReplaceSelect (oTextbox, sText)\r\n", " {\r\n", " if (isIE) {\r\n", " var oRange = document.selection.createRange();\r\n", " oRange.text = sText;\r\n", " oRange.collapse(true);\r\n", " oRange.select(); \r\n", " } else if (isMoz) {\r\n", " var iStart = oTextbox.selectionStart;\r\n", " oTextbox.value = oTextbox.value.substring(0, iStart) sText oTextbox.value.substring(oTextbox.selectionEnd, oTextbox.value.length);\r\n", " oTextbox.setSelectionRange(iStart sText.length, iStart sText.length);\r\n", " }\r\n", "\r\n", " oTextbox.focus();\r\n", " }\r\n", "\r\n", " function autocompleteMatch (sText, arrValues)\r\n", " {\r\n", " var retMatches = \"\"; \r\n", " \r\n", " for (var i=0; i < arrValues.length; i )\r\n", " {\r\n", " if (arrValues[i].indexOf(sText) == 0)\r\n", " {\r\n", " retMatches = arrValues[i] ',';\r\n", " }\r\n", " }\r\n", " \r\n", " if (retMatches.length > 0)\r\n", " {\r\n", " retMatches = retMatches.substr(0, retMatches.length - 1);\r\n", " } \r\n", "\r\n", " return retMatches;\r\n", " }\r\n", "\r\n", " function __DoAutoComplete(oEvent, id)\r\n", " {\r\n", " var oTextbox = document.getElementById(id '_textBox');\r\n", " var frame = document.getElementById(id '_autoCompleteFrame');\r\n", " var arrValues = document[id '_data'];\r\n", " \r\n", " switch (oEvent.keyCode) \r\n", " {\r\n", " case 38: //up arrow \r\n", " case 40: //down arrow\r\n", " case 37: //left arrow\r\n", " case 39: //right arrow\r\n", " case 33: //page up \r\n", " case 34: //page down \r\n", " case 36: //home \r\n", " case 35: //end \r\n", " case 13: //enter \r\n", " case 9: //tab \r\n", " case 27: //esc \r\n", " case 16: //shift \r\n", " case 17: //ctrl \r\n", " case 18: //alt \r\n", " case 20: //caps lock\r\n", " case 8: //backspace \r\n", " case 46: //delete\r\n", " return true;\r\n", " break;\r\n", " \r\n", " default:\r\n", " textboxReplaceSelect(oTextbox, String.fromCharCode(isIE ? oEvent.keyCode : oEvent.charCode));\r\n", " var iLen = oTextbox.value.length;\r\n", "\r\n", " var sMatches = autocompleteMatch(oTextbox.value, arrValues);\r\n", "\r\n", " if (sMatches.length > 0)\r\n", " {\r\n", " var arrMatches = sMatches.split(',');\r\n", " oTextbox.value = arrMatches[0];\r\n", " textboxSelect(oTextbox, iLen, oTextbox.value.length);\r\n", " \r\n", " if (arrMatches.length > 1)\r\n", " {\r\n", " frame.style.display = 'inline';\r\n", " frame.height = '100';\r\n", " \r\n", " frame.contentWindow.document.body.innerHTML = '';\r\n", " for (var i = 0; i < arrMatches.length; i )\r\n", " {\r\n", " frame.contentWindow.document.body.innerHTML = '<div style=\"width: 100%; cursor: default\" onmouseover=\"this.style.backgroundColor=\\'#316AC5\\'; this.style.color=\\'white\\';\" onmouseout=\"this.style.backgroundColor=\\'\\'; this.style.color=\\'black\\';\" onclick=\"parent.document.getElementById(\\'' id '_textBox\\').value = this.innerHTML\">' arrMatches[i] '</div>';\r\n", " }\r\n", " \r\n", " frame.contentWindow.document.body.style.backgroundColor = 'white';\r\n", " frame.contentWindow.document.onclick = function() { document.getElementById(id '_autoCompleteFrame').style.display = 'none'; };\r\n", " } \r\n", " } \r\n", " \r\n", " return false;\r\n", " } \r\n", " }\r\n", "</script>\r\n", ""); Page.ClientScript.RegisterClientScriptBlock(typeof(string), "__DoAutoComplete", script); } if (!Page.ClientScript.IsClientScriptBlockRegistered(MakeUniqueID("data"))) { Page.ClientScript.RegisterClientScriptBlock(typeof(string), MakeUniqueID("data"), string.Format("<script language=\"javascript\" type=\"text/javascript\">document.{0}_data = {1}</script>", MakeUniqueID(null), ToJsStringArray(AutoCompleteData))); } #endregion } protected override void RenderContents(HtmlTextWriter output) { output.WriteLine(string.Format("<div onmouseleave=\"document.getElementById('{0}').style.display = 'none';\" style=\"width:{1}\" >", MakeUniqueID("autoCompleteFrame"), Width)); textBox.RenderControl(output); output.WriteLine("<br />"); autoCompleteFrame.RenderControl(output); output.WriteLine("</div>"); } #endregion } }
源程序下载:
https://files.cnblogs.com/lsmsky/autocompletetextbox.rar