AutoComplet
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,以下是链接:https://files.cnblogs.com/xxfss2/Demo.rar