自动完成功能AutoCompleteTextBox

最近封装的AutoCompleteTextBox。我们知道,ASP.NET本身的TextBox也是支持一定的AutoComplete功能的,但是那是依赖浏览器实现的,并不能指定自定义的AutoComplete候选项。本文列举的AutoCompleteTextBox则弥补了这个缺憾。只需设置AutoCompleteTextBox.AutoCompleteData属性,传递一个string[],就能使TextBox支持自定义候选项了。


AutoComplete逻辑

如果没有匹配当前输入的候选项,则同一般的TextBox;
如果只有一个候选项与当前输入匹配,则自动完成
如果有超过一个候选项与当前输入匹配,则在textbox中自动完成第一个候选项,并弹出包含所有候选项的弹出框。


实现源码

源码是在VS2005编译的,不过实际上几乎没有使用依赖2.0的语法,在vs2003下经极少修改就同样能编译的。

复制  保存
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

posted @ 2008-10-23 09:34  Landy_di  阅读(380)  评论(0编辑  收藏  举报