首页 > 编程 > .NET > 正文

ASP.NET: Custom AutoCompleteTextBox WebControl

2024-07-10 13:11:41
字体:
来源:转载
供稿:网友

  这是一个teddy最近封装的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
    {
        private members#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

        properties#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

        overriden members#region overriden members

        protected override void createchildcontrols()
        {
            create textbox#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

            create autocompleteframe#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)
        {
            register client script block#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
    }
}

下载

http://teddyma.cnblogs.com/files/teddyma/autocompletetextbox.zip


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表