65.9K
CodeProject 正在变化。 阅读更多。
Home

带自动搜索和弹出工具提示的 ASP.NET DropDownList 和 ListBox 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.28/5 (28投票s)

2006年3月10日

4分钟阅读

viewsIcon

246522

downloadIcon

1203

对标准的 DropDownList 和 ListBox 控件的简单而非常有用的补充。

Sample Image - xNetComponents.gif

引言

在我参与的一个项目中,使用了许多 ASPX 页面,其中包含用于选择人员、部门等的 DropDownListListBox。我的客户问我是否可以通过键盘输入字符来选择合适的项目。于是,我试图让他工作更轻松。起初,这只是 JavaScript 代码,现在它有了 ASP.NET 服务器控件。因此,我想描述两个 ASP.NET 服务器控件:xNetDropDownListxNetListBox,它们可以在用户在键盘上输入字符时,将焦点移至列表中第一个最合适的项目。

背景

这两个组件的工作原理是相似的;因此,我将重点描述 xNetDropDownList。在客户端,xNetDropDownList 表现为一个 HTML <select> 框。当元素获得焦点时,上方会出现一个工具提示。输入的字符会显示在工具提示中,焦点会移动到列表中的第一个合适项目。按 Escape 键会删除所有输入的字符,并将焦点移至第一个项目。退格键会删除最后一个输入的字符。在删除字符后,焦点会移至与工具提示中的文本对应的列表项。当元素失去焦点时,工具提示会消失。

为了正确工作,项目列表必须按升序排序!

实现

xNetDropDownList 组件继承自 System.Web.UI.WebControls.DropDownList。它添加了几个新属性。这些属性主要用于设置工具提示的视觉参数。这些属性在表格中有所描述

公共属性 类型 描述
ToolTipHide bool 获取或设置工具提示的可见性;false 显示工具提示,true 不显示。
ToolTipBackColor Color 获取或设置背景颜色。
ToolTipBorderColor Color 获取或设置边框颜色。
ToolTipBorderStyle BorderStyle 获取或设置边框样式。
ToolTipBorderWidth 单位 获取或设置边框宽度。
ToolTipFontFamily 字符串 获取或设置字体名称的有序数组。
ToolTipFontSize FontUnit 获取或设置字体大小。
ToolTipFontBold bool 获取或设置一个值,该值指示字体是否为粗体。
ToolTipForeColor Color 获取或设置文本颜色。
ToolTipOffsetLeft int 获取或设置工具提示左上角的水平偏移量,相对于 DropDownListListBox 的坐标。测量单位是像素。在属性设计器中,只输入数字(整数)。
ToolTipOffsetTop int 获取或设置工具提示左上角的垂直偏移量,相对于 DropDownListListBox 的坐标。测量单位是像素。在属性设计器中,只输入数字(整数)。
ToolTipPadding 单位 获取或设置文本和边框之间的间距。
ToolTipInitialWidth 单位 获取或设置初始宽度。
ToolTipZIndex int 获取或设置 z-index。
ToolTipSaveText bool 获取或设置是否在工具提示中保存输入的文本。如果为 true,则在元素失去焦点并重新获得焦点时会保存输入的文本。如果为 false,则输入的文本将丢失。

这张图解释了 ToolTipOffsetLeftToolTipOffsetTop 属性

在列表中搜索合适项目的搜索功能是通过 JavaScript 实现的。

xOnFocus() 函数用于创建和设置工具提示的属性。当 <select> 元素首次获得焦点时,会创建一个新的 HTML 元素 <div>;否则,该函数会根据 ToolTipSaveTextToolTipHide 属性中的设置来控制工具提示的行为。

function xOnFocus(elm)
{
    var el = document.getElementById('div_' + elm.id);
    if (!el)
    {
        var xdiv = document.createElement('DIV');
        xdiv.id = 'div_' + elm.id;
        xdiv.noWrap = true;
        xdiv.style.position = 'absolute';
        
        xdiv.ToolTipText = '';
        xdiv.style.color = elm.ToolTipForeColor;
        xdiv.style.width = elm.ToolTipInitialWidth;
        xdiv.style.padding = elm.ToolTipPadding;
        xdiv.style.display  = (elm.ToolTipHide == 'false') ? 'inline' : 'none';
        xdiv.style.backgroundColor = elm.ToolTipBackColor; 
        xdiv.style.borderColor = elm.ToolTipBorderColor; 
        xdiv.style.borderStyle = elm.ToolTipBorderStyle; 
        xdiv.style.borderWidth = elm.ToolTipBorderWidth; 
        xdiv.style.fontFamily = elm.ToolTipFontFamily; 
        xdiv.style.fontSize = elm.ToolTipFontSize; 
        xdiv.style.fontWeight = elm.ToolTipFontBold;
        xdiv.style.zIndex = elm.ToolTipZIndex;

    if (document.documentElement && document.documentElement.scrollTop)
        xdiv.style.top = document.documentElement.scrollTop + 
          elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
    else
        xdiv.style.top = document.body.scrollTop + 
          elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
    if (document.documentElement && document.documentElement.scrollLeft)
        xdiv.style.left = document.documentElement.scrollLeft + 
          elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
    else
        xdiv.style.left = document.body.scrollLeft + 
          elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);

    elm.insertAdjacentElement('afterEnd', xdiv);
    }
    else
    {
    if (document.documentElement && document.documentElement.scrollTop)
        el.style.top = document.documentElement.scrollTop + 
          elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
    else
        el.style.top = document.body.scrollTop + 
          elm.getBoundingClientRect().top - parseInt(elm.ToolTipOffsetTop);
    if (document.documentElement && document.documentElement.scrollLeft)
        el.style.left = document.documentElement.scrollLeft + 
          elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);
    else 
        el.style.left = document.body.scrollLeft + 
          elm.getBoundingClientRect().left + parseInt(elm.ToolTipOffsetLeft);

        if (elm.ToolTipSaveText == 'false') 
        {
            el.innerText = '';
            el.ToolTipText = '';
        }
        el.style.display  = (elm.ToolTipHide == 'false') ? 'inline': 'none';
    }
}

xOnBlur() 函数隐藏工具提示。

function xOnBlur(elm)
{
    var el = document.getElementById('div_' + elm.id);
    if (el) el.style.display = 'none';
}

xOnKeyUp() 函数处理以下按键:Esc、BackSpace 和 Enter。请注意,如果 AutoPostBack 属性为 true,除了 DropDownListListBox 控件的标准行为外,当用户按下 Enter 键时,还会发生自动回发到服务器。

function xOnKeyUp(key_event)
{
    var lb = key_event.srcElement;

    var el = document.getElementById('div_' + lb.id);
    if (el)
    {
        if (key_event.keyCode == 8)
        {
            key_event.returnValue = false;
            if (el.ToolTipText.length > 0)
                el.ToolTipText = 
                  el.ToolTipText.substr(0, el.ToolTipText.length - 1);

            el.innerText = el.ToolTipText + ' ';
            xFindItem(el.ToolTipText, lb);
        }

        if (key_event.keyCode == 27)
        {
            key_event.returnValue = false;

            el.ToolTipText = '';
            el.innerText = '';
            xFindItem(el.ToolTipText, lb);
        }

        if (key_event.keyCode == 13)
        {
            key_event.returnValue = true;
            if (lb.AutoPostBack == 'true') lb.onchange();
        }
    }
}

xOnKeyPress() 函数处理字母数字字符。

function xOnKeyPress(key_event)
{
    var lb = key_event.srcElement;

    var el = document.getElementById('div_' + lb.id);
    if (el)
    {
        if (key_event.keyCode != 13)
        {  
            el.ToolTipText = el.ToolTipText + String.fromCharCode(key_event.keyCode); 
            el.innerText = el.ToolTipText +' ';
            xFindItem(el.ToolTipText, lb);
        }
        key_event.returnValue = false;
     }
}

xFindItem() 函数是主要函数,负责在列表中搜索项目。

function xFindItem(s, lb)
{
    s = s.toUpperCase();
    
    var slen = s.length;
    var lblen = lb.length;
    var lbo = lb.options;
        
    if (slen == 0 && lblen > 0)
    { 
        lb.selectedIndex = 0;
        return;
    }

    for (i = 0; i < lblen; i++)
    {    
        if (lbo[i].text.toUpperCase().substr(0, slen) == s)
        {
            lb.selectedIndex = i;
            break;
        }
    }
}

该组件已在 Internet Explorer 6.0 版本中进行了测试。

使用代码

您可以像使用其他 Web 服务器控件一样使用此控件。

示例

演示项目包含三个页面

  • Sample1.aspx - xNetDropDownListxNetListBox 包含直接通过 ListItem Collection Editor 输入的姓氏和名字列表。此页面演示了组件的一般工作方式。
  • Sample2.aspx - xNetDropDownListxNetListBox 连接到 Northwind 数据库(MS SQL Server)。请记住更改连接字符串中的用户名和密码!
  • Sample3.aspx – 展示了不同的外观变体。

历史

  • 2006 年 3 月 10 日
    • 文章已提交。
  • 2006 年 6 月 12 日
    • Enter 键问题已解决。
  • 2006 年 6 月 18 日
    • Tab 键的相同问题已得到纠正。
  • 2006 年 8 月 6 日
    • 通过代码设置属性的问题已解决。
  • 2006 年 10 月 15 日
    • 窗口 resize 后工具提示位置问题以及 IE6 带有 DOCTYPE 的问题已修复。感谢 Ondra Jires。
© . All rights reserved.