基于 Ajax.NET 的查找服务器控件实现






4.27/5 (23投票s)
2005年9月1日
4分钟阅读

137021

583
本文介绍如何基于 Ajax.NET 框架构建一个查找服务器控件。
引言
AJAX 是当今最流行的词汇之一。这个概念并非新鲜事物,但不知何故,在过去半年里变得流行起来。随着 Web 应用程序的普及,用户对更丰富、更快的界面提出了要求。而 AJAX 非常有助于改善 Web 应用程序的用户体验。
让我向您展示一个真实用户需求的例子。我们的一位客户需要一种快速选择用户故事和 Bug 的方法。例如,Bug 可以链接到用户故事,并且有一个用于此目的的下拉列表。但是,当下拉列表中有大约 100 个项目时,它根本无法使用,而查找控件将使选择更简单(类似于 Google Suggest)。因此,我们决定在我们的产品中使用 AJAX 来实现这些功能,改进用户界面,并使其响应更灵敏。
AJAX 对我来说是全新的。我曾经读过一些关于它的通用文章来了解一些概念,但由于缺乏工具和现成的库而没有尝试过。然而,最近我发现了 Ajax.NET – 一个非常强大的框架,支持异步回调。其中的示例很简单,所以我决定用它来实现我的目标。
在本文中,我将描述使用 Ajax.NET 创建查找控件的经验。要构建查找控件,您需要做几件事:
- 一个服务器方法,它将返回匹配记录的列表。
- 一个 JavaScript,它将处理回发并显示匹配记录的列表。
- 在 ASPX/ASCX 页面上的一个输入字段。
我不会在这里描述 Ajax.NET 的安装,因为它非常简单,而且有一些很棒的资源供您查看。
服务器端部分
这部分确实很简单。我需要实现的只是一个简单的返回匹配记录 `ArrayList` 的方法,并注册包含该方法的类。
public class Main : Page
{
private void Page_Load(object sender, EventArgs e)
{
Utility.RegisterTypeForAjax(typeof (Main));
}
[AjaxMethod()]
public ArrayList GetSearchItems(string query)
{
// use real method ti query data from database instead
ArrayList items = GetRecords();
ArrayList matchItems = new ArrayList();
foreach (string item in items)
{
if (item.ToLower().StartsWith(query.ToLower()))
matchItems.Add(item);
}
return matchItems;
}
private ArrayList GetRecords()
{
ArrayList items = new ArrayList();
items.Add("Ted");
items.Add("Teddy");
items.Add("Mark");
items.Add("Alfred");
return items;
}
. . .
`GetSearchItems` 方法从任何源获取所有记录的列表,并过滤掉那些以 `query` 参数开头的记录。`query` 是用户在输入字段中键入的内容。
客户端部分
首先,我决定编写一个非常简单的 JavaScript,它会在查询输入字段的正下方显示一个包含找到记录的 `DIV`。我心想“又近了一步”。但需要选择下面的其中一项。最简单的方法是将所有项目变成超链接,并在单击时用正确的值填充查询字段。以下是我的成果:
<INPUT id=search type=text name=search runat="server"
autocomplete ="off">
<div id="list"></div>
需要 `autocomplete="off"` 来告知浏览器不要显示输入字段的可能值。否则,我们的控件将无法正常工作。
function GetSearchItems_CallBack(response) {
var div = document.getElementById("list");
div.innerHTML = "";
if (response.value != null && response.value.length > 0) {
for (var i = 0; i < response.value.length; ++i){
div.innerHTML +=
"<a href=\"javascript:Fill('" + response.value[i] + "');\">" +
response.value[i] + "</a><br />";
}
}
JavaScript 的 `GetSearchItems_CallBack` 函数应该绑定到 `onkeydown` 事件。这可以在代码隐藏文件或直接在 `*.aspx` 页面上完成。让我们使用代码隐藏文件。
private void Page_Load(object sender, EventArgs e)
{
search.Attributes.Add("onkeydown",
"javascript:Main.GetSearchItems(this.value,
GetSearchItems_CallBack);");
Utility.RegisterTypeForAjax(typeof ( Main ));
}
结果如下:
虽然这是最简单的方法,但它并不十分可用。您输入一些内容,然后单击出现的列表中的一个链接 – 操作太多了。真正需要的是一些炫酷的键盘支持。用户应该能够使用上/下键进行列表导航,并使用 Enter 键完成选择。
寻找 JavaScript
我以前从未在 JavaScript 中处理过按键事件,并且懒得自己编写一个庞大而复杂的脚本。我懂 JavaScript,但不如 C# 熟练,所以我第一个反应是:“让我们找一些现成的东西来适应我们的需求。”我必须说,免费脚本并不多。我花了一个小时才找到一个不错的。所以不能错过这个引用。感谢 Julian Robichaux 提供了这个非常棒的脚本,附带了很棒的注释(这对于免费脚本来说很少见,对于商业脚本也是如此:))
该脚本提供了一个查询服务器的函数,但我需要一个自定义函数。幸运的是,唯一需要的更改是 `mainLoop` 函数。
mainLoop = function() {
val = escape(queryField.value);
if(lastVal != val && searching == false){
var response = Main.GetSearchItems(val);
showQueryDiv('smi', response.value); lastVal = val;
}
setTimeout('mainLoop()', 100);
return true;
};
应该通过 `onload` 处理程序启用该脚本。
<body onload="InitQueryCode('search')">
最终,我在很短的时间内得到了我想要的结果。但解决方案是不可重用的,所以我决定创建一个简单的服务器控件。
服务器控件
AJAX 查找服务器控件是一个非常简单的东西。现有解决方案的以下部分应该是可自定义的:
- 回调函数的名称。
- JavaScript 文件的路径。
- 颜色,如匹配列表的背景和高亮,`div` 的内边距等。
可以发明其他东西,但我不需要更多,而且总的来说,如果近期不需要,我不喜欢增加复杂性。
实现相当简单。我们可以让我们的控件继承自 `TextBox`。然后,我们所需要做的就是设置一些变量并注册一些 JavaScript 函数。
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace play
{
/// <summary>
/// AjaxLookup.cs
/// </summary>
public class AjaxLookup : TextBox
{
private string scriptFile = "";
private string callBackFunction = "";
private string backgroundColor = "#EEE";
private string highlightColor = "#CCC";
private string font = "Verdana";
private string divPadding = "2px";
private string divBorder = "1px solid #CCC";
public string ScriptFile
{
get { return scriptFile; }
set { scriptFile = value; }
}
public string CallBackFunction
{
get { return callBackFunction; }
set { callBackFunction = value; }
}
public string BackgroundColor
{
get { return backgroundColor; }
set { backgroundColor = value; }
}
public string HighlightColor
{
get { return highlightColor; }
set { highlightColor = value; }
}
public string DivFont
{
get { return font; }
set { font = value; }
}
public string DivPadding
{
get { return divPadding; }
set { divPadding = value; }
}
public string DivBorder
{
get { return divBorder; }
set { divBorder = value; }
}
public AjaxLookup()
{
this.Attributes.Add("autocomplete", "off");
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
// bind script that contains almost all logic
Page.RegisterStartupScript("LoadScript",
"<script language="'JavaScript'" src='" + ScriptFile + "'>" +
"</script>");
// include UI settings
string styles = String.Format(
@"<script language="'JavaScript'">
var DIV_BG_COLOR = '{0}';
var DIV_HIGHLIGHT_COLOR = '{1}';
var DIV_FONT = '{2}';
var DIV_PADDING = '{3}';
var DIV_BORDER = '{4}';
</script>",
BackgroundColor, HighlightColor, DivFont,
DivPadding, DivBorder);
Page.RegisterStartupScript("LookupStyles", styles);
// initialize postback handling
Page.RegisterStartupScript(
"RegisterScript",
"<script language="'JavaScript'">" +
"InitQueryCode('" + this.ClientID + "')</script>");
// set correct calllback function
Page.RegisterStartupScript("RegisterCallBack",
@"<script language="'JavaScript'">
mainLoop = function() {
val = escape(queryField.value);
if(lastVal != val && searching == false){
var response = " + CallBackFunction + @"(val);
showQueryDiv('smi', response.value); lastVal = val;
}
setTimeout('mainLoop()', 100);
return true;};
</script>");
}
}
控件可以这样使用:
<Ajax:AjaxLookup
Runat="Server"
id="search"
BackgroundColor="#EEE"
DivBorder="1px solid #CCC"
DivPadding="2px"
DivFont="Arial"
HighlightColor="#C30"
CallBackFunction="Main.GetSearchItems"
ScriptFile="lookup.js" />
这是查找控件在生产环境中的样子:
这个实现并非完美,但足够好,可以作为起点。您可以提高灵活性,添加一些额外的参数等等。
结论
总的来说,Ajax.NET 可以帮助实现许多有用的功能。从最简单的东西,如查找控件开始是合理的,但我希望将来我们项目中的许多 UI 部分将基于 AJAX。
联系方式
- 联系邮箱:michael [at] targetprocess.com。
- 博客.