[ASP.net/Ajax] TextBox輸入文字自動完成(非WebService和使用WebService寫法整理)
如果想在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的方式,才能成功。