[转]StyledAutoComplete - 支持丰富样式的自动补全

    原文链接:http://www.cnblogs.com/JeffreyZhao/archive/2007/06/12/StyleAutoComplete.html

    几个月前,我扩展了Atlas CTP时期的的AutoCompleteBehavior,到了ASP.NET AJAX正式版之后这个扩展自然就不能用了。其实这段时间内有不少朋友问我该如何做到像Google Suggest那样带丰富样式的自动补全功能,但是由于各种原因(比如时间不够,还有现在的AutoCompleteBehavior复杂的许多,或者仅仅是“懒”……),我没有深入地研究它,更别提对它的扩展了。

  最近手头正好有些时间,也就逼迫自己耐着性子读了读AutoCompleteBehavior的代码。不得不承认Ajax Control Tookit本身也在不停的发展之中,现在无论服务器端还是客户端都提供了非常强大的基础组件,解决了大量常见问题,使得开发工作变得简单了许多。与此形成鲜明对比的是文档的缺乏,建议对于深入ASP.NET AJAX感兴趣的朋友读一下Ajax Control Toolkit的代码,这对于您理解ASP.NET的控件模型与客户端组件的开发大有碑益。

  我扩展了现有的AutoCompleteBehavior,使AutoComplete的功能能够轻松支持丰富的样式。我在这里暂时不对实现方法进行分析,不过大家可以下载代码并进行一些测试,如果有任何问题还可以反馈给我。另外,我认为目前StyledAutoCompleteBehavior的设计还不够灵活,如果有什么需要但是无法实现的功能请您告诉我,也欢迎大家给我一些功能设计方面的建议。自动补全是一个很常用的功能,可惜Ajax Control Toolkit中提供的功能实在不够用。

  在我的扩展中,StyledAutoCompleteExtender继承了AutoCompleteExtender,StyledAutoCompleteBehavior继承了AutoCompleteBehavior,在编写时我也尽可能的保持了原有的功能不变,因此大家在使用时完全可以将AutoCompleteExtender的标签直接改为StyledAutoComplteExtender而不会影响到任何功能。与AutoCompleteExtender相比,StyledAutoCompleteExtender多了一个属性ItemTemplate用于指定自动补全中每一项的模板。例如我们要实现Google Suggest那样的功能,则需要这样使用StyledAutoCompleteExtender:

<jeffz:StyledAutoCompleteExtender
runat="server"
BehaviorID="AutoCompleteEx"
ID="autoComplete1"
TargetControlID="myTextBox"
ServicePath="AutoComplete.asmx"
ServiceMethod="GetSearchCompletionList"
MinimumPrefixLength="2"
CompletionInterval="1000"
EnableCaching="true"
CompletionSetCount="10"
CompletionListCssClass="completionListElement"
CompletionListItemCssClass="listItem"
CompletionListHighlightedItemCssClass="highlightedListItem">
<ItemTemplate>
<span style="float:left;" class="keywords">{0}</span>
<span style="float:right;" class="result">{1}&nbsp;results</span>
<div style="clear:both;"></div>
</ItemTemplate>
</jeffz:StyledAutoCompleteExtender>

 

  请注意ItemTemplate里的内容,它将作为自动补全每一项的HTML。而诸如{0}、{1}等则作为占位符,最终在显示时将会使用服务器端返回的内容进行替换。为了配合这个功能,服务器端的Web Service方法返回值也有所变化:

[WebMethod]
public IList<object[]> GetSearchCompletionList(string prefixText, int count)
{
if (count == 0)
{
count = 10;
}
Random random = new Random();
IList<object[]> items = new List<object[]>(count);
for (int i = 0; i < count; i++)
{
char c1 = (char)random.Next(65, 90);
char c2 = (char)random.Next(97, 122);
char c3 = (char)random.Next(97, 122);
items.Add(new object[] { prefixText + c1 + c2 + c3, random.Next(10000, 300000) });
}
return items;
}

 

  方法的返回值变成了一个存放object数组的列表,每个object数组将会作为自动补全中每一项的信息发送到客户端。object数组的每个元素将用于替换模板中的占位符(事实上,我使用了String.format方法来获得每一项的HTML,因此事实上您也可以在这里使用本地化的功能等等)。

  模拟Google Suggest的效果如下(点击这里查看示例):

 

  新的控件将“补全的内容”和“显示的内容”进行了分离。目前的控件将object数组的第一个元素(下标为0)作为“补全的内容”,在显示的时候,我们可以将其忽略。例如,下面的代码将会模拟Windows Live Mail中Email提示的功能(事实上,Live Mail的这部分自动补全是纯客户端功能,我这里模拟的仅仅是“样式”)。

<head id="Head1" runat="server">
<title>Untitled Page</title>
<style type="text/css">
.completionListElement
{
visibility : hidden;
margin : 0px!important;
background-color : inherit;
color : windowtext;
border : buttonshadow;
border-width : 1px;
border-style : solid;
cursor : pointer;
overflow : auto;
text-align : left;
list-style-type : none;
font-family : Verdana;
font-size: 11px;
padding : 0;
}
.listItem
{
background-color: white;
padding : 1px;
}
.highlightedListItem
{
background-color: #e9f5f7;
padding : 1px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:TextBox runat="server" ID="myTextBox" Width="500"
style="height:14px; border: solid 1px gray; font-family:Verdana; font-size: 11px;" />
<jeffz:StyledAutoCompleteExtender
runat="server"
BehaviorID="AutoCompleteEx"
ID="autoComplete1"
TargetControlID="myTextBox"
ServicePath="AutoComplete.asmx"
ServiceMethod="GetEmailCompletionList"
MinimumPrefixLength="2"
CompletionInterval="1000"
EnableCaching="true"
CompletionSetCount="10"
CompletionListCssClass="completionListElement"
CompletionListItemCssClass="listItem"
CompletionListHighlightedItemCssClass="highlightedListItem"
DelimiterCharacters=",;">
<ItemTemplate>{1}</ItemTemplate>
</jeffz:StyledAutoCompleteExtender>
</form>
</body>

 

  在这里,ItemTemplate的内容很简单,只是将服务器端返回的每个object数组的第二个元素显示在页面上,而第一个元素则作为补全的文本。它对应的Web Service方法如下所示:

private static string[] emails = new string[]
{
"\"jeffrey zhao at yahoo\" &lt;jeffz@yahoo.com&gt;",
"\"jeffrey zhao at yahoo china\" &lt;jeffz@yahoo.com.cn&gt;",
"\"jeffrey zhao at live mail\" &lt;jeffz@live.com&gt;",
"\"jeffrey zhao at gmail\" &lt;jeffz@gmail.com&gt;"
};
[WebMethod]
public IList<object[]> GetEmailCompletionList(string prefixText, int count)
{
IList<object[]> items = new List<object[]>();
prefixText = prefixText.Trim();
foreach (string email in emails)
{
if (email.Contains(prefixText))
{
string encoded = email.Replace(prefixText, "<b>" + prefixText + "</b>");
items.Add(new object[] { HttpUtility.HtmlDecode(email) + ";", encoded });
}
}
return items;
}

 

  服务器端传回的每个object数组长度为2,第一个元素用于自动补全,第二个元素用于显示,因此需要将关键字部分进行加粗。使用效果如下(点击这里查看示例): 

 

   另外,正像Live Mail的功能一样,StyleAutoCompleteBehavior也支持输入多个Email——这是新版AutoCompleteBehavior提供的功能,请注意AutoCompleteBehavior的DelimiterCharacters属性,它是一个字符串,字符串中的每个字符即为分隔符。

目前StyledAutoCompleteBehavior只在FireFox和IE下进行了测试。

 

点击这里查看Google Suggest模拟示例

点击这里查看Windows Live Mail模拟示例

点击这里下载StyleAutoCompleteExtender/Behavior控件以及示例代码。

posted @ 2007-08-27 20:21  scgw  阅读(618)  评论(0编辑  收藏  举报