2012年10月29日 星期一

使用 AutoCompleteExtender 為網頁添加「自動完成」效果


OK! 你已經知道怎麼安裝 AJAX Control Toolkit 而且已經安裝好了,然後你想利用 AutoCompleteExtender 來為某些 TextBox 控制項添加自動完成的功能(很簡單),而此功能所提示的項目清單要來自另一個 WCF Service,而不是來自網頁本身提供的 Web Method 或某個 Web Service(其實也很簡單)。最後,還想套用自訂的 CSS 來改善自動完成清單的顯示樣式。

開發工具

  • Visual Studio 2010
  • AJAX Control Toolkit .NET 4

快速入門
  1. 把一個 ToolkitScriptManager 和一個 TextBox 控制項拖到你的 ASP.NET 網頁上。
  2. 為 TextBox 加上 AutoCompleteExtender:從 TextBox 控制項的智慧標籤選單中點 Add Extender,然後選擇 AutotCompleteExtender。參考下圖:

  3. 同樣利用 TextBox 控制項的智慧標籤選單,點選其中的 Add Autocomplete page method,如下圖所示。


  4. 這樣會為你目前的網頁添加一個 GetCompletionList 方法。你只要把取得自動完成清單的邏輯寫在這裡就行了。參考底下的程式碼:
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string[] GetCompletionList(string prefixText, int count, string contextKey)
{
    return new string[] { "台北市", "新北市", "台中市"};
}

此方法套用了兩個特徵項:WebMethodAttribute 和 ScriptMethodAttribute,表示此方法可以被當作 Web Service 呼叫,也可以在用戶端網頁中透過 jQuery 或其他 AJAX 技術呼叫。這裡的 ScriptMethodAttribute 可以省略,但 WebMethodAttribute 不可省略,否則用戶端會呼叫不到此方法。

方法的參數 prefixText 就是使用者在網頁上輸入的字串;你可以根據此資訊來決定要傳回的清單項目,例如,prefixText 若為 "台",就傳回以「台」開頭的縣市名稱,如台北市、台中市、台南市等等。這裡我只是簡單的傳回三個固定的縣市名稱。

參數 count 就是對應到用戶端網頁中的 AutoCompletExtender 控制項的 CompletionSetCount 屬性,代表用戶端想要從伺服器端取得幾筆建議項目。參數 contextKey 則是對應到 ContextKey 屬性,這是給你自己額外運用的自訂參數。

要注意的是,此方法的名稱可以讓你任意修改,但方法的參數名稱絕對不可改,連大小寫都要完全一樣,否則用戶端網頁會呼叫不到。 

你可以開啟網頁的 .aspx 原始碼,看看 AutoCompletExtender 控制項還有哪些屬性。比較重要的是 ServicePath 和 ServiceMethod 屬性。由於此範例是把取得建議清單的 method 直接產生在目前網頁的類別裡,所以你應該只會看到 ServiceMethod 屬性有設定值,而沒有 ServicePath。當你修改了伺服器端的 GetCompletionList 方法的名稱,記得要一併修改用戶端網頁中的 ServiceMethod 屬性,這兩個名稱若不相符,自動完成的效果肯定出不來。

接著在瀏覽器中檢視此網頁,試一下效果。當你在 TextBox 中輸入超過三個字元時,TextBox 下方就會出現自動完成的建議清單。輸入幾個字元就要觸發自動完成,是由 AutoCompletExtender 的 MinimumPrefixLength 屬性來控制。

後端改用 WCF Service

如果你想要寫一個 WCF Service,提供自動完成的建議清單給其他 ASP.NET 網頁,就不要像前面示範的步驟 3 那樣自動產生網頁方法,而是由我們手動建立這個方法。

做法很簡單,首先在網站中加入一個 AJAX-enabled WCF Service,將它命名為 AddressService.svc。

然後開啟 AddressService.cs,為 AddressService 類別加入我們的 GetCompleteList 方法:

[OperationContract]
public string[] GetCompletionList(string prefixText, int count, string contextKey)
{
    string[] cities = new string[] { "台北市", "新北市", "台中市", "高雄市", "台南市", "桃園縣" };

    return cities.Where<string>(s => s.StartsWith(prefixText)).Take<string>(count).ToArray<string>();
}

這裡我稍微加了一點比對字串的邏輯:字串陣列 cities 用來模擬我們從資料庫取回的查詢結果,然後再從這個陣列中選取前 n 筆(由 Take 方法負責)符合前導字串 prefixText 的縣市名稱。

接著修改 ASP.NET 網頁上的 AutoCompleteExtender 控制項的屬性:
  • ServicePath="AddressService.svc"
  • ServiceMethod="GetCompletionList"
  • MinimumPrefixLength="1" (因為縣市名稱只有三個字,我們希望使用者只輸入一個字就能立刻出現建議清單。)

ASP.NET 網頁原始碼:

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <ajaxToolkit:AutoCompleteExtender ID="TextBox1_AutoCompleteExtender" runat="server"
        ServicePath="AddressService.svc" ServiceMethod="GetCompletionList" TargetControlID="TextBox1"
        UseContextKey="True" MinimumPrefixLength="1">
    </ajaxToolkit:AutoCompleteExtender>

執行結果如下圖:




套用 CSS 來改變外觀

前面的範例執行結果,那個自動完成清單顯示的位置離 TextBox 太遠了,而且我想要修改顯示的字型和顏色,怎麼辦呢?還好 AutoCompleteExtender 還提供了一些屬性可讓我們套用自訂的 CSS 來改變其預設外觀。主要是這幾個屬性:

  • CompletionListCssClass
  • CompletionListItemCssClass
  • CompletionListHighlightedItemCssClass

簡單起見,我就把 CSS 直接內嵌在網頁裡。修改後的 ASPX 原始碼如下(部分標籤省略):

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        .completionListElement
        {
            visibility: hidden;
            margin: 0px !important;
            background-color: inherit;
            color: black;
            border: solid 1px gray;
            cursor: pointer;
            text-align: left;
            list-style-type: none;
            font-family: Verdana;
            font-size: 12px;
            padding: 0;
        }
        .listItem
        {
            background-color: white;
            padding: 1px;
        }
        .highlightedListItem
        {
            background-color: #c3ebf9;
            padding: 1px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <ajaxToolkit:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
    </ajaxToolkit:ToolkitScriptManager>
    <div>
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <ajaxToolkit:AutoCompleteExtender ID="TextBox1_AutoCompleteExtender" runat="server"
            ServicePath="AddressService.svc" ServiceMethod="GetCompletionList" TargetControlID="TextBox1"
            CompletionListCssClass="completionListElement" CompletionListItemCssClass="listItem"
            CompletionListHighlightedItemCssClass="highlightedListItem" UseContextKey="True"
            MinimumPrefixLength="1">
        </ajaxToolkit:AutoCompleteExtender>
    </div>
    </form>
</body>
</html>

套用 CSS 之後的執行結果如下圖:

沒有留言:

張貼留言