[ASP.net/Ajax] TextBox輸入文字自動完成(非WebService和使用WebService寫法整理)

[ASP.net/Ajax] TextBox輸入文字自動完成(非WebService和使用WebService寫法整理)

官網說明 AutoComplete Sample

如果想在TextBox上輸入文字,即時出現一個Layer文字列表,類似Google搜尋那樣

一般的做法是使用WebService吧

1.先看WebService

以個人測試Web site範例,我是開一個WebService資料夾在根目錄下,然後加入一個WebService.asmx

同時Visual Studio也會產生一份WebService.cs檔在App_Code資料夾內

WebService.cs內的程式碼:

using System.Collections;
using System.Data;
using System.Data.SqlClient;


[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {

    [System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
    //方法不可宣告static
    public string[] GetCompletionList(string prefixText, int count)
    {
        //資料庫連線字串
        string connStr = @"Data Source=.\SQLEXPRESS;AttachDbFilename="
                     + System.Web.HttpContext.Current.Server.MapPath("~/App_Data/NorthwindChinese.mdf") + ";Integrated Security=True;User Instance=True";

        ArrayList array = new ArrayList();//儲存撈出來的字串集合

        using (SqlConnection conn = new SqlConnection(connStr))
        {
            DataSet ds = new DataSet();
            string selectStr = @"SELECT Top (" + count + ") CompanyName FROM Customers Where CompanyName Like '" + prefixText + "%' Order by CustomerID ASC";
            SqlDataAdapter da = new SqlDataAdapter(selectStr, conn);
            conn.Open();
            da.Fill(ds);
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                array.Add(dr["CompanyName"].ToString());
            }

        }

        return (string[])array.ToArray(typeof(string));

    } 

    
}

接著新增一個UseWebService.aspx檔案在根目錄

aspx程式碼

<%@ Page Language="C#" AutoEventWireup="true"  %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<html>
<head >
</head>
<body>
    <form id="form1" runat="server">

    <asp:ScriptManager ID="ScriptManager1" runat="server" />

    <asp:TextBox ID="TextBox1" runat="server" />

    <asp:AutoCompleteExtender
           ID="AutoCompleteExtender1"
           runat="server"
           MinimumPrefixLength="1"
           TargetControlID="TextBox1"
           ServiceMethod="GetCompletionList"
           ServicePath="WebService/WebService.asmx"
           CompletionSetCount="15" 
    />
    <!--AutoCompleteExtender成員說明
    MinimumPrefixLength:最少輸入幾個字就呼叫Method
    TargetControlID:哪個TextBox要有自動完成功能
    ServiceMethod:呼叫的Method名
    ServicePath:WebService路徑
    CompletionSetCount:要列出幾筆資料
    -->
    </form>
</body>
</html>

結束,因為Code-Behind沒有要寫程式,所以我把UseWebService.aspx.cs宰了

 

2.接著再看不使用WebService的做法

先在App_Code裡新增一個AutoComplete_WebPage.cs類別

AutoComplete_WebPage.cs的程式碼

using System.Data;
using System.Data.SqlClient;
using System.Collections;

//類別繼承System.Web.UI.Page目的是為了讓其他aspx.cs可以再繼承下來使用
public class AutoComplete_WebPage :System.Web.UI.Page
{
    [System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
    //一定要宣告成static才有效果
    public static string[] GetCompletionList(string prefixText, int count)
    {
        //連線字串
        string connStr = @"Data Source=.\SQLEXPRESS;AttachDbFilename="
                     + System.Web.HttpContext.Current.Server.MapPath("~/App_Data/NorthwindChinese.mdf") + ";Integrated Security=True;User Instance=True";

        ArrayList array = new ArrayList();//儲存撈出來的字串集合

        using (SqlConnection conn = new SqlConnection(connStr))
        {
            DataSet ds = new DataSet();
            string selectStr = @"SELECT Top (" + count + ") CompanyName FROM Customers Where CompanyName Like '" + prefixText + "%' Order by CustomerID ASC";
            SqlDataAdapter da = new SqlDataAdapter(selectStr, conn);
            conn.Open();
            da.Fill(ds);
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                array.Add(dr["CompanyName"].ToString());
            }

        }

        return (string[])array.ToArray(typeof(string));

    } 

}

接著在網站根目錄下新增一個NoWebService.aspx

NoWebService.aspx程式碼

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="NoWebService.aspx.cs" Inherits="NoWebService" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<html>
<head runat="server">
</head>
<body>
    <form id="form1" runat="server">

    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <asp:TextBox ID="TextBox1" runat="server" />

    <asp:AutoCompleteExtender
           ID="AutoCompleteExtender1"
           runat="server"
           TargetControlID="TextBox1"
           MinimumPrefixLength="1"
           ServiceMethod="GetCompletionList"
           CompletionSetCount="15" 
    />




    </form>
</body>
</html>

NoWebService.aspx.cs程式碼

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

//繼承AutoComplete_WebPage類別
public partial class NoWebService : AutoComplete_WebPage
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

 

3.最後分別把UseWebService.aspx或NoWebService.aspx執行起來,效果一樣

(註:Firefox 更新到4.x版以上可以支援ASP.net Ajax的自動完成)

整理一下兩者寫法差異

 

 

 

 

 

 

  新增項目 App_Code/cs檔類別 App_Code/cs檔方法 網頁程式
使用WebService WebService.asmx、WebService.cs檔 類別加[System.Web.Script.Services.ScriptService]屬性,
並繼承System.Web.Services.WebService
方法不可宣告static否則無效 aspx頁面的AutoCompleteExtender擴充項
須指定ServicePath
不使用WebService 加入一個類別AutoComplete_WebPage.cs 類別繼承System.Web.UI.Page 一定要宣告成static才有效果 aspx.cs須繼承自訂類別

範例程式檔

 

不使用WebService做法的原理:

每支aspx程式要有自己的public static Method(服務方法),若寫在MasterPage或WebUserControl的話,ServiceMethod會抓不到,所以只好用繼承的方式,讓有需要做自動完成功能的aspx程式繼承自訂類別,而該自訂類別就是實現自動完成功能的System.Web.UI.Page子類別

====================

2011/9/2 眼尖的讀者可以發現以上的SQL查詢會有SQL Injection危險,所以以上 SqlDataAdapter 的查詢語法最好改成以下:

string selectStr = @"SELECT Top (" + count + ") CompanyName FROM Customers Where CompanyName Like  @prefixText + '%' Order by CustomerID ASC";

SqlDataAdapter da = new SqlDataAdapter(selectStr, conn);
da.SelectCommand.Parameters.AddWithValue("@prefixText", prefixText);

再附上黑暗執行緒網友的jQuery AutoComplete懶人包文章

MSDN相關討論:http://social.msdn.microsoft.com/Forums/zh-TW/236/thread/0ffc9ef8-3577-4f2c-9867-aae692235717

2011/10/19 追加說明

如果是在MasterPage或是WebControl做自動完成的話,建議採用WebService的方式,才能成功。