AutoComplete這個控件網上已經很多了,以前在一個項目中用過一次,但是沒有很好的去封裝它。最近在學習控件開發,感覺這個控件以后還會用到,便嘗試着寫了一個。
雖然這個控件網上隨便一搜就有,但為了能將它融合到自己的框架中,自己開發一個也是有必要的,而且開發的過程,也是學習和提高的契機。
首先展示一下使用的方法和效果吧
1.新建一個空白的頁面,引入必要的腳本和樣式文件(Jquery和自己的腳本庫,這個腳本庫包含的不僅僅是AuctoComplete這個控件需要用到的腳本),然后拖入或者手寫一個AutoComplete控件,本質上它是一個經過擴展的TextBox控件
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type ="text/javascript" src ="http://www.cnblogs.com/js/jquery-1.4.1-vsdoc.js"></script>
<script type ="text/javascript" src ="http://www.cnblogs.com/js/Core.js"></script>
<link href="http://www.cnblogs.com/style/web.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<Jiuzh:AutoComplete runat="server" ID ="acExample" ></Jiuzh:AutoComplete>
</form>
</body>
</html>
2.雙擊控件,為它增加一個ontextchanged事件函數,同時設置控件的MinStart屬性,該屬性表示引發查詢的最小字符數,另外還有一個用於綁定查詢時額外參數的Params屬性,這里沒有用到。HTML代碼和C#代碼分別如下
<form id="form1" runat="server">
<Jiuzh:AutoComplete runat="server" ID ="acExample" ontextchanged="acExample_TextChanged" MinStart="2" ></Jiuzh:AutoComplete>
</form>
protected List<string> acExample_TextChanged(object sender)
{
List<string> result = new List<string>();
result.Add("1213");
result.Add("1234");
result.Add("5345");
result.Add("1241");
return result.Where(s => s.Contains(acExample.Text)).ToList();
}
大功告成,啟動該頁面,在文本框中輸入 12 ,結果如下圖所示
怎么樣,使用方式還算簡單吧。
========================接下來是萬眾矚目的代碼解析了==============================
首先這個控件用到的技術很簡單,主要是Jquery的AJAX接口和ASP.NET的控件開發技術。
我想對於新手來說肯定對於該控件的ontextchanged事件函數很感興趣,沒有AUTOPOSTBACK屬性為TRUE,它是怎么觸發服務器事件的呢,另外事件的函數簽名怎么也變了,只有一個sender 參數。
首先我們看下頁面生成后的HTML代碼
<input onkeyup="AutoComplate(this,2,{})" name="acExample" type="text" id="acExample" />
看,一個INPUT控件而已,在生成頁面時為它綁定了onkeyup事件,onkeyup事件執行了AutoComplate函數,該函數有3個參數,第一個參數不用說,第二個參數就是剛才設置的MinStart參數,第三個參數則是查詢時綁定的額外參數.
接下來看AutoComplate這個函數
function AutoComplate(obj, len, param) {
var ctl = $(obj);
var val = ctl.val();
var ctlId = ctl.attr("id");
if (val.length == 0) {
$("#" + ctlId + "_Auto").hide();
return;
}
if (val.length < len)
return;
var div = $("#" + ctlId + "_Auto");
if (div.length == 0) {
div = $("<div id=\"" + ctlId + "_Auto\" style =\"position:absolute; display:none; border:1px solid #817f82; background-color:#ffffff; width:200px\"></div>");
$('body').append(div);
}
param ["__EVENTTARGET"]=ctlId;
param[ctlId] = val;
var wu_nopar = window.location.href.split("?")[0].split("/");
var pageName = wu_nopar[wu_nopar.length - 1];
$.post(pageName+"?action=list", param, function (data) {
var result = eval(data);
if (result.length > 0) {
div.html("");
var table = $("<table style='width:100%' ><tbody></tbody></table>");
for (var i = 0; i < result.length; i++) {
var tr = $("<tr><td >" + result[i] + "</td></tr>");
tr.mouseover(function () {
$(this).addClass('JZac');
});
tr.mouseout(function () {
$(this).removeClass('JZac');
});
tr.click(function () {
$(obj).val($(this).children().eq(0).html());
div.hide();
});
table.append(tr);
}
div.append(table);
var of = $(obj).offset();
var top = of.top + $(obj).height();
div.css("top", top + 5);
div.css("left", of.left);
div.width($(obj).width());
div.show();
}
else
div.hide();
});
}
對於熟悉Jquery的來說,以上代碼沒什么好解釋的,關鍵是這兩句
param ["__EVENTTARGET"]=ctlId;
param[ctlId] = val;
param參數我剛才解釋過是查詢時的額外參數,但在這個AutoComplete函數中,我為它額外增加了兩個參數,第一個參數名為__EVENTTARGET,值為當前的控件Id,第二個參數為當前的控件Id,值為控件的文本值。有了這兩個參數,並且以POST方式提交,在服務器端,我們的AutoComplete控件的ontextchanged事件便觸發了。也就是說在AutoComplete函數中,我模擬了觸發控件服務器端事件的數據並以AJAX的方式提交。
最后來看控件的源代碼。首先我定義了一個委托用於替代默認的委托
public delegate List <string > AutoCompleteHandler(object sender);
接着是控件代碼
[ToolboxData("<{0}:AutoComplete runat=server></{0}:AutoComplete>")]
public class AutoComplete : TextBox
{
public new event AutoCompleteHandler TextChanged;
private Params _params=new Params ();
public Params Params
{
get
{
return _params;
}
}
[TypeConverter (typeof (uint ))]
public string MinStart { get; set; }
protected virtual void OnAutoCompleteChanged(EventArgs e)
{
if (TextChanged != null)
{
List<string> result = TextChanged(this);
JavaScriptSerializer ser = new JavaScriptSerializer();
string json = ser.Serialize(result);
Context.Response.ContentType = "text/plain";
Context.Response.Write(json);
Context.Response.End();
}
}
protected override void RaisePostDataChangedEvent()
{
OnAutoCompleteChanged(EventArgs.Empty);
// base.RaisePostDataChangedEvent();
}
public override void RenderControl(HtmlTextWriter writer)
{
StringBuilder sb=new StringBuilder ();
for (int i = 0; i < Params.Count; i++)
{
sb.AppendFormat("{0}:{1}", Params .Keys [i], Params [i]);
}
writer.AddAttribute("onkeyup", "AutoComplate(this,"+MinStart+",{" + sb.ToString () + "})");
base.RenderControl(writer);
}
}
首先是這句 public new event AutoCompleteHandler TextChanged;例用new關鍵字使得TextChanged事件執行我之前定義的委托。然后在OnAutoCompleteChanged函數中,取得TextChanged事件返回的結果,同時Response.End();返回數據。
============================OVER=========================================
以上便是該控件的介紹,希望對大家有幫助,有不對的地方還請指出。
因為有人需要一個完整的代碼包,便做了一個DEMO,以下是鏈接:http://files.cnblogs.com/xxfss2/Demo.rar