在07年1月开始进行的名古屋大学项目和EPS社内管理系统中均使用了Ajax技术。在个别需要频繁和后台进行交互的画面中使用Ajax技术,做到了画面无刷新的提交数据和业务处理,明显的提高了数据处理速度,画面无刷新的即时数据展现也提升了用户操作体验感觉。
在Asp.net编程中,用服务器控件数据绑定在画面上数据展示是最广泛的应用,但是服务器控件的数据绑定是服务器行为,必须画面初始化或画面刷新才能显示绑定的数据或更新后的数据。这样在频繁改变条件动态显示数据的情况下,比如DataGrid控件中的分页处理,一般的必须画面刷新一次才能得到下一页的数据,这样画面频繁的刷新操作,对用户的体验感觉不是很好。在实际项目中有如下图这样一个画面:点击画面中左边列表中的选择按钮,即变绿选中列表中的一行,同时右边列表重新初始化显示为根据左边选中行的条件检索出来的数据。如果用传统方法来实现这个画面,用户点击一次选择按钮,整个画面就要刷新一次,而且还要设置状态记录当前选择的行,以便画面刷新后记住变绿的选中行,这样不仅编程复杂而且用户操作感觉也不好。引入Ajax后,点击选择按钮,用Javascript方法无刷新更新右边列表,减少了编码工作量同时也让用户有了C/S客户端操作即时展现数据的体验感觉。
Ajax与服务器控件的交互绑定目前并没有统一和很好的解决方案,基本的解决思路都是通过Ajax将后台显示的数据转换为Html代码,然后在前台画面用Javascript输出。在实际项目中,Ajax与DataGrid的交互方式进行了多次探索和改进,现在已经实现了一个较为简单的绑定方式,应用效果也不错,下文将分别介绍这几种实现方式。(具体源代码可以参考EPS项目源代码,本文将不对Ajxa的基本应用配置详细介绍,具体配置方式可以参考第一期学报文章《Ajax技术在Asp.net中的简单应用》)
方式一:前台JS循环遍历生成Html代码
在上图所示的画面中,点击某一行的选择按钮选择一行后,将该行的担当ID得到通过Ajax传到后台,后台根据担当ID检索数据库,得到的结果集放置到DataSet结构中,然后传到前台Js方法中,在Js方法中循环遍历DataSet中表的每一行,以<tr><td>的方式按行生成Html代码,然后用innerHTML的方式将生成的Html代码输出到画面指定位置。这种方式是最基本的实现方式,其他方式都是在这种方式基础上的延伸,优点是易于理解,缺点是按行遍历生成Html代码的编程繁琐,画面显示列表中每一行的样式控制调试困难。
[代码示例一]:用Ajax方法传入担当ID执行Sql得到包含数据的DataSet
[AjaxPro.AjaxMethod] //AjaxPro处理 public DataSet InitPageList2(object userID) { //Session过期判断 if(!CheckSession()) { return null; } DataSet dsList = new DataSet(); if(userID != null) { ExecuteSqlBll ExecSql = new ExecuteSqlBll(); //根据担当ID执行Sql,返回DataSet结果集 dsList = ExecSql.ExecuteDataSetSQL(string.Format(SUMDAYSQL, userID); } return dsList; } |
[代码示例二]:前台用Js方法循环遍历生成显示数据的Html代码
//取得后台执行Sql得到的DataSet var ds = ProjectMng.Web.TotalConfirm.PersonInpSum.InitPageList2(userID).value; //取得表的行数 var iLen = ds.Tables[0].Rows.length; //构造显示数据的table var strHtml = "<table width='333' bordercolor='#000000' class='TableBorderAndFont' style='BORDER-COLLAPSE: collapse' border='1' align='left' cellpadding='0' cellspacing='0'>"; //循环遍历表的每一行构造table for(i=0;i<iLen;i++) { strHtml = strHtml + "<tr height='15px' align='center'><td align='center' width='160'>" + ds.Tables[0].Rows[i].YearMonth; //取得第i行YearMonth列的数据 strHtml = strHtml + "</td><td align='center' width='160'>" + ds.Tables[0].Rows[i]. SumDayTime + "</td></tr>" } strHtml = strHtml + "</table>"; //取得画面中显示数据table的位置 var objList2 = document.getElementById("divList2"); //数据显示 objList2.innerHTML = strHtml; |
方式二:调用服务器控件的render方法输出显示数据的Html
这种方式是将后台执行Sql得到的结果集直接绑定到DataGrid等服务器控件上,然后调用控件的render方法输出控件显示数据的Html代码到HtmlTextWriter中,然后将HtmlTextWriter返回到前台,显示到innerHTML中。
[代码示例三]:用Ajax方法将数据绑定到DataGrid然后得到显示数据的Html
[Ajax.AjaxMethod] public string GetAjaxTable(DataSet ds) { //这个方法就是得到datagrid生成出来的html //实例化一个datagird类并设置好数据源 DataGrid dg = new DataGrid(); dg.DataSource = ds.Tables[0]; dg.DataBind(); //实例化一个HtmlTextWriter的类 System.Text.StringBuilder strb = new System.Text.StringBuilder(); System.IO.StringWriter sw = new System.IO.StringWriter( strb ); System.Web.UI.HtmlTextWriter htw = new HtmlTextWriter( sw ); //执行控件的render并输出到HtmlTextWriter里 dg.RenderControl( htw ); string strHtml = strb.ToString(); //返回包含显示数据的Html代码 return strHtml; } |
这种方式简单明了,编程也相对较容易,值得注意的是绑定数据的DataGrid必须在类中创建,
这样就带来一个很大的缺点:显示数据的样式控制复杂,因为在后台给DataGrid调整样式是很困难和复杂的事情,没有在前台加css样式表方便易用,所以在这种方式虽然简单却不实用,只适合于对显示数据样式要求不高的情况下使用。在这种实现方式的基础上探索实现了第三种方式,充分结合了后台DataGrid数据绑定和前台css控制样式。
方式三:用自定义控件实现DataGrid数据绑定和样式控制输出显示数据的Html
方式二最大的缺点是难以控制样式,而在画面中注册的DataGrid可以加载css样式表,但是在实际项目中调试发现,在画面上注册的DataGrid在Ajax方法中却无法绑定数据,因为画面没有提交和刷新。既然放在画面上不行,那么就思考是否可以既有一个载体可以让DataGrid加载样式表又能在Ajax方法中绑定数据,试验后发现自定义用户控件可以达到这一目的。
这种方式的原理是:首先定义一个UserControl,在UserControl中注册DataGrid,加载样式表及模板列等,然后在Ajax方法中加载UserControl,从UserControl中找到带有样式表的DataGrid,绑定数据,用render方法取得显示数据的Html。
[代码示例四]:在UserControl中注册DataGrid,加载样式表及模板列
[Ajax.AjaxMethod] public string ShowTheControl(DataTable objSource) { System.IO.StringWriter sw = new System.IO.StringWriter(); HtmlTextWriter hw = new HtmlTextWriter(sw); //得到UserControl实体 Control control = ReturnUC(); //DataGrid数据绑定 InitializeUC(control); //得到显示数据的Html代码 control.RenderControl(hw); return sw.ToString(); } //得到UserControl实体 protected Control ReturnUC(string name) { string applicationPath = HttpContext.Current.Request.ApplicationPath; if (applicationPath == "/") applicationPath = string.Empty; string ControlPath = applicationPath + "/TotalConfirm/" + name; Control uc = this.LoadControl(ControlPath); return uc; } //UserControl中的DataGrid数据绑定 protected override void InitializeUC (Control UC) { //取得UserControl中加载了样式表的DataGrid AjDataGrid = (DataGrid)UC.FindControl("dg_AjaxGrid"); //DataGrid数据绑定 AjDataGrid.DataSource = dtSource; AjDataGrid.DataBind(); } |
这样直接使用[代码示例一]中的objList2.innerHTML就可以在指定位置显示检索得到数据,如果显示数据的样式调整,直接在UserControl的界面中可视化调整DataGrid样式就可以了,非常简单,代码量少,也不易出错。
综合以上三种实现方法,本质虽然一致,但是最后一种方式明显简单易于控制,实现了 Ajax 与服务器控件的数据绑定,达到了运用 DataGrid 等高级服务器控件在画面中无刷新的动态显示数据的功能,而且在实际项目中得到了广泛的应用,效果良好。