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






4.28/5 (28投票s)
2006年3月10日
4分钟阅读

246522

1203
对标准的 DropDownList 和 ListBox 控件的简单而非常有用的补充。
引言
在我参与的一个项目中,使用了许多 ASPX 页面,其中包含用于选择人员、部门等的 DropDownList
和 ListBox
。我的客户问我是否可以通过键盘输入字符来选择合适的项目。于是,我试图让他工作更轻松。起初,这只是 JavaScript 代码,现在它有了 ASP.NET 服务器控件。因此,我想描述两个 ASP.NET 服务器控件:xNetDropDownList
和 xNetListBox
,它们可以在用户在键盘上输入字符时,将焦点移至列表中第一个最合适的项目。
背景
这两个组件的工作原理是相似的;因此,我将重点描述 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 |
获取或设置工具提示左上角的水平偏移量,相对于 DropDownList 或 ListBox 的坐标。测量单位是像素。在属性设计器中,只输入数字(整数)。 |
ToolTipOffsetTop |
int |
获取或设置工具提示左上角的垂直偏移量,相对于 DropDownList 或 ListBox 的坐标。测量单位是像素。在属性设计器中,只输入数字(整数)。 |
ToolTipPadding |
单位 |
获取或设置文本和边框之间的间距。 |
ToolTipInitialWidth |
单位 |
获取或设置初始宽度。 |
ToolTipZIndex |
int |
获取或设置 z-index。 |
ToolTipSaveText |
bool |
获取或设置是否在工具提示中保存输入的文本。如果为 true ,则在元素失去焦点并重新获得焦点时会保存输入的文本。如果为 false ,则输入的文本将丢失。 |
这张图解释了 ToolTipOffsetLeft
和 ToolTipOffsetTop
属性
在列表中搜索合适项目的搜索功能是通过 JavaScript 实现的。
xOnFocus()
函数用于创建和设置工具提示的属性。当 <select>
元素首次获得焦点时,会创建一个新的 HTML 元素 <div>
;否则,该函数会根据 ToolTipSaveText
和 ToolTipHide
属性中的设置来控制工具提示的行为。
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
,除了 DropDownList
和 ListBox
控件的标准行为外,当用户按下 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 -
xNetDropDownList
和xNetListBox
包含直接通过ListItem
Collection Editor 输入的姓氏和名字列表。此页面演示了组件的一般工作方式。 - Sample2.aspx -
xNetDropDownList
和xNetListBox
连接到 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。