使用 Autocomplete Extender 实现类似 Google 的建议






4.36/5 (11投票s)
如何使用 autocomplete extender 提供联系人建议
引言
此示例演示了如何使用 ASP.NET AJAX Control Toolkit 中的 AutoCompleteExtender
控件,并在不修改它的情况下自定义其行为。
背景
我喜欢 Google 的建议功能,并曾想在我的任何项目中使用它。ASP.NET 的 AJAX Control Toolkit 有一个类似的控件(AutoCompleteExtender
),它提供了完成此功能所需的基本项。我搜索了它的用法,找到了很多示例,但并不满意。它们都只使用此扩展器填充单个字段。
然后我想到一个主意,为什么不只用一个扩展器填写联系人详细信息,包括姓名、电子邮件地址和电话号码,而且不修改任何提供的功能,以便我们的代码可以用于新版本。下面是填写联系人表单后的效果。

Using the Code
让我们来看看 AutoCompleteExtender
是如何工作的。下面是工具包示例站点上对它的描述。
AutoComplete
是一个 ASP.NET AJAX 扩展器,可以附加到任何TextBox
控件,并将该控件与弹出面板关联,以显示以textbox
中键入的前缀开头的单词。由 Web 服务提供的候选单词的
dropdown
位于textbox
的左下方。
它说这个控件将从 Web 服务获取数据,并且可以附加到 TextBox
控件(它只能附加到一个控件)。当用户开始在该 TextBox
控件中键入时,它会从配置的 Web 服务获取建议列表。
所以我们需要两样东西:一个是我们的示例联系人页面,另一个是一个 Web 服务。这是我们的 Web 服务代码。
using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script;
using System.Web.Script.Serialization;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;
using AjaxControlToolkit;
/// <summary>
/// Summary description for SuggestionService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class SuggestionService : System.Web.Services.WebService {
public SuggestionService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
[ScriptMethod()]
public string[] GetContacts(string prefixText, int count, string contextKey) {
List<string> items = new List<string>();
JavaScriptSerializer serializer = new JavaScriptSerializer();
ContactManager manager = new ContactManager();
List<contact> contacts = manager.GetContacts
(int.Parse(contextKey), prefixText, count);
foreach (Contact c in contacts)
{
items.Add(AutoCompleteExtender.CreateAutoCompleteItem
(c.FullName, serializer.Serialize(c)));
}
return items.ToArray();
}
}
您会注意到服务和 Web 方法上的一些额外修饰。您必须用“ScriptService
”属性修饰此服务,因为没有它,您将无法从客户端脚本访问它。
[ScriptService()]
public class SuggestionService : System.Web.Services.WebService {
我们的 webmethod
将返回 JSON 格式的 string
项列表,因此它也需要在其上添加 ScriptMethod
属性。
[WebMethod]
[ScriptMethod()]
public string[] GetContacts(string prefixText, int count, string contextKey) {}
此外,您还注意到我以不同的方式返回了这些数据。我使用了 AutoCompleteExtender
来创建自己的条目,因为我想从 Web 服务返回一些额外数据,以便填充联系人表单上的所有相关字段。此功能仅在 AJAX Control Toolkit 的最新版本(1.0.20229.0)中可用。在此之前不可用。它提供键值对,如果您想为内部 ID 显示友好名称列表,这是一个非常有用的功能。CreateAutoCompleteItem
方法接受两个参数,第一个是要显示的文本,第二个是可以通过页面上的任何自定义脚本使用的值。
items.Add(AutoCompleteExtender.CreateAutoCompleteItem
(c.FullName, serializer.Serialize(c)));
现在我还有另一个障碍需要克服,如何传递复杂的联系人数据。现在 JSON 来救援我了。我使用 JavaScriptSerializer
序列化了我的联系人对象。
到目前为止,我一直夸耀我的联系人对象有点复杂,下面是它的样子。下面是我的 Contact
和 Phone
类。
/// <summary>
/// Summary description for Contact
/// </summary>
public class Contact
{
protected int _contactId;
public int ContactId
{
get { return _contactId; }
}
protected int _companyId;
public int CompanyId
{
get { return _companyId; }
set { _companyId = value; }
}
protected string _firstName;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
protected string _lastName;
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public string FullName
{
get { return _firstName + ' ' + _lastName; }
}
protected string _email;
public string Email
{
get { return _email; }
set { _email = value; }
}
public int _homePhoneId;
public int _workPhoneId;
protected Phone _homePhone;
public Phone HomePhone
{
get { return _homePhone; }
set { _homePhone = value; }
}
protected Phone _workPhone;
public Phone WorkPhone
{
get { return _workPhone; }
set { _workPhone = value; }
}
public Contact() : this(0, 0, 0)
{
}
public Contact(int id) : this(id, 0, 0)
{
}
public Contact(int id, int homephone, int workphone)
{
_contactId = id;
_homePhoneId = homephone;
_workPhoneId = workphone;
}
}
/// <summary>
/// Summary description for Phone
/// </summary>
public class Phone
{
protected int _phoneId;
public int PhoneId
{
get { return _phoneId; }
}
protected string _areaCode;
public string AreaCode
{
get { return _areaCode; }
set { _areaCode = value; }
}
protected string _prefix;
public string Prefix
{
get { return _prefix; }
set { _prefix = value; }
}
protected string _number;
public string Number
{
get { return _number; }
set { _number = value; }
}
protected string _extension;
public string Extension
{
get { return _extension; }
set { _extension = value; }
}
public Phone() : this(0)
{
}
public Phone(int id)
{
_phoneId = id;
}
}
现在我们需要处理我们的联系人页面。下面是它的基本 HTML。此联系人表单包含姓、名、电子邮件地址和电话号码字段。每个电话号码又包含前缀、区号、号码和分机字段。
<div style="border: 1px solid rgb(204, 204, 204); padding: 10px; width: 400px;">
<table cellspacing="0" cellpadding="0" border="0">
<tbody><tr>
<td style="width: 100px; text-align: right;">First Name:</td>
<td><asp:textbox runat="server" id="txtFirstName" /></td>
</tr>
<tr>
<td style="width: 100px; text-align: right;">Last Name:</td>
<td><asp:textbox runat="server" id="txtLastName" /></td>
</tr>
<tr>
<td style="width: 100px; text-align: right;">Home Phone:</td>
<td>
<table cellspacing="0" cellpadding="0" border="0">
<tbody><tr>
<td><asp:textbox columns="3"
runat="server" id="txtHPAreaCode" /></td>
<td>-<asp:textbox columns="3"
runat="server" id="txtHPPrefix" /></td>
<td>-<asp:textbox columns="3"
runat="server" id="txtHPNumber" /></td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td style="width: 100px; text-align: right;">Work Phone:</td>
<td>
<table cellspacing="0" cellpadding="0" border="0">
<tbody><tr>
<td><asp:textbox columns="3"
runat="server" id="txtWPAreaCode" /></td>
<td>-<asp:textbox columns="3"
runat="server" id="txtWPPrefix" /></td>
<td>-<asp:textbox columns="3"
runat="server" id="txtWPNumber" /></td>
<td> x </td>
<td><asp:textbox columns="3"
runat="server" id="txtWPExtension" /></td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td style="width: 100px; text-align: right;">Email Address :</td>
<td><asp:textbox runat="server" id="txtEmail" /></td>
</tr>
</tbody></table>
</div>
要在此页面上使用 AutoCompleteExtender
,请先放置 ScriptManager
控件,然后放置 AutoCompleteExtender
控件,并将其 TargetControlId
设置为姓氏 TextBox
控件。这将为姓氏 TextBox
控件添加一些额外的属性。这些属性与其附加的扩展器有关,您可以在 AutoCompleteExtender
示例页面上找到它们的描述。我们必须设置其中一些属性来激活它的工作。
首先指定 ServicePath
并将其设置为我们刚刚创建的 Web 服务,然后设置 ServiceMethod
,它将返回建议列表。这将是我们服务中的 Web 方法。我们也可以使用 context key,这有助于我们过滤建议。在我们的例子中,我使用它来传递当前公司信息,以便我可以返回特定公司的联系人。
这样就完成了我们的基本设置。如果您现在测试此页面,在姓氏字段中键入两个字母后,您将看到一个建议列表,并且当您从该列表中选择任何项时,只有姓氏字段会被设置为选定的姓名。所有其他字段将保持空白。
现在我们需要添加我们的魔术代码,它将使我们能够实现我们的目标。
<script type="text/javascript">
function OnContactSelected(source, eventArgs)
{
var results = eval('(' + eventArgs.get_value() + ')');
$get('txtFirstName').value = results.FirstName;
$get('txtLastName').value = results.LastName;
if (results.HomePhone.AreaCode != null)
$get('txtHPAreaCode').value = results.HomePhone.AreaCode;
if (results.HomePhone.Prefix != null)
$get('txtHPPrefix').value = results.HomePhone.Prefix;
if (results.HomePhone.Number != null)
$get('txtHPNumber').value = results.HomePhone.Number;
if (results.WorkPhone.AreaCode != null)
$get('txtWPAreaCode').value = results.WorkPhone.AreaCode;
if (results.WorkPhone.Prefix != null)
$get('txtWPPrefix').value = results.WorkPhone.Prefix;
if (results.WorkPhone.Number != null)
$get('txtWPNumber').value = results.WorkPhone.Number;
if (results.WorkPhone.Number != null)
$get('txtWPExtension').value = results.WorkPhone.Extension;
if (results.Email != null)
$get('txtEmail').value = results.Email;
}
</script>
但在那之前,我们需要为我们的扩展器添加一些客户端行为。我们需要将扩展器的 OnClientItemSelected
属性设置为上述 JavaScript 函数。此函数将解析 value
属性,该属性是从我们的 Web 服务传递的有效 JSON 数据,并使用这些解析后的数据设置相应的字段。
到此,我们的示例就完成了。现在您可以自己测试一下了。
历史
- 2008-06-24 - 我的第一个 AJAX 自动扩展尝试