无刷新分页要用到自己定义的存储过程:
alter proc usp_DivMemberByPage @pageIndex int, @pageSize int, @total int output //注意:这里不要忘记output as begin select * from ( select *,row_number() over(order by uId asc) RowId from Member ) Temp where Temp.RowId between (@pageIndex-1)*@pageSize+1 and (@pageIndex)*@pageSize select @total=count(1) from Member end
测试自己的存储过程 declare @total int exec usp_DivMemberByPage 1,10,@total output //注意:这里也要加output select @total
然后在动软的三层架构里加扩展
1.在DAL层复制Member.cs 改名为MemberExt,去掉构造方法和其他方法
/// <summary> /// 数据访问类:Member /// </summary> public partial class Member { #region ExtensionMethod /// <summary> /// 自定义存储过程:获取分页会员信息 /// </summary> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="total"></param> /// <returns></returns> public DataTable GetMemberPageByProc(int pageIndex, int pageSize, out int total) { String connStr = DbHelperSQL.connectionString; SqlParameter p1 = new SqlParameter("@pageIndex", SqlDbType.Int) { Value=pageIndex}; SqlParameter p2 = new SqlParameter("@pageSize", SqlDbType.Int) { Value=pageSize}; SqlParameter p3 = new SqlParameter("@total", SqlDbType.Int); //注意:这里的参数名必须和存储过程中形参名字一样 p3.Direction = ParameterDirection.Output; //注意:这里要设置第三个参数的输出方向 DataSet dSet = new DataSet(); using (SqlDataAdapter sda = new SqlDataAdapter("usp_DivMemberByPage", connStr)) //注意:这里不能写成usp_DivMemberByPage @pageIndex, @pageSize, @total output的,只要写存储过程名字就行了 { sda.SelectCommand.CommandType = CommandType.StoredProcedure; sda.SelectCommand.Parameters.Add(p1); sda.SelectCommand.Parameters.Add(p2); sda.SelectCommand.Parameters.Add(p3); sda.Fill(dSet); } total = Convert.ToInt32(p3.Value); //注意:必须给total赋值 p3.Value是Object类型,需要转换 return dSet.Tables[0]; } #endregion ExtensionMethod
1.在BLL层复制Member.cs 改名为MemberExt,去掉构造方法和其他方法
#region ExtensionMethod
/// <summary> /// 自定义存储过程:获取分页会员信息 /// </summary> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="total"></param> /// <returns></returns> public List<Model.Member> GetMemberPageByProc(int pageIndex, int pageSize, out int total) { return DataTableToList(dal.GetMemberPageByProc(pageIndex, pageSize,out total)); } #endregion ExtensionMethod
然后在web中的处理无刷新分页的一般处理程序应该这么写:
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; int pageIndex = context.Request["pageIndex"] == null ? 1 : int.Parse(context.Request["pageIndex"]); int pageSize = context.Request["pageSize"] == null ? 10 : int.Parse(context.Request["pageSize"]); BLL.Member memberMain = new BLL.Member(); int total = 0; List<Model.Member> list = memberMain.GetMemberPageByProc(pageIndex, pageSize, out total); String _divString = Comm.LaoHePager.ShowPager(pageSize, pageIndex, total, "MemberManage/LoadAllMemberToJson.ashx"); JavaScriptSerializer js = new JavaScriptSerializer(); String temp = js.Serialize(new { JsonContent=list, divString=_divString}); //注意:这里是匿名类 context.Response.Write(temp); }
生成分页字符串的LaoHePager类是这么写的:
public class LaoHePager { public static String ShowPager(int pageSize, int currentPage, int totalCount, String redirectTo) { //取出页容量 pageSize = pageSize == 0 ? 3 : pageSize; //取出总页数 int totalPage = Math.Max((totalCount + pageSize - 1) / pageSize, 1); StringBuilder sb = new StringBuilder(); //判断当前索引是否有效 if (currentPage < 1 || currentPage > totalPage) { return String.Empty; } //只有当前索引(currentIndex > 1)显示首页、上一页 if (currentPage > 1) { sb.AppendFormat("<li><a class='head page' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, 1, pageSize, "首页"); sb.AppendFormat("<li><a class='prev page' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, currentPage-1, pageSize, "上一页"); } //显示当前页前后各5页的索引 int distince = 5; for (int i = 0; i < 10; i++) { int index = currentPage - distince + i; if (index >= 1 && index <= totalPage) { if (currentPage != index) { sb.AppendFormat("<li><a class='page' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, index, pageSize, index); } else { sb.AppendFormat("<li><a id='currPage' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, index, pageSize, index); } } } //只有当前索引(currentIndex < 总页数)显示尾页、下一页 if (currentPage < totalPage) { sb.AppendFormat("<li><a class='next page' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, currentPage + 1, pageSize, "下一页"); sb.AppendFormat("<li><a class='tail page' href='{0}?pageIndex={1}&pageSize={2}' >{3}</a></li> \n", redirectTo, totalPage, pageSize, "尾页"); } sb.AppendFormat("<span class='summary'>第{0}页 / 共{1}页</span>\n", currentPage, totalPage); return sb.ToString(); } }
然后,在前端写一个函数,注意,必须自定义一个函数,因为无刷新分页为导航按钮绑定事件,需要调用自身
function LoadMemerToJson(pageIndex, pageSize) { $.ajax({ url: 'MemberManage/LoadAllMemberToJson.ashx', data: { 'pageIndex': pageIndex, 'pageSize': pageSize }, type: 'POST', dataType: 'json', success: function (data) { //加载会员列表 LoadMemberByJson(data.JsonContent); //加载分页字符串 LoadDivString(data.divString); //加载分页导航<a>链接后立即绑定点击事件 $('#divString li a').click(function () { var currPageIndex = GetQueryStringValue($(this).attr('href'), 'pageIndex'); //这里是通过函数解析QueryStrng,稍后说 var currPageSize = GetQueryStringValue($(this).attr('href'), 'pageSize'); LoadMemerToJson(currPageIndex, currPageSize); //这里就用到了加载自身 return false; }); }, error: function (xhr, textStatus, errorThown) { alert('服务器响应失败,错误信息:' + textStatus); } }); }
这是解析QueryString的Javascript函数,QueryString就是url中键值对啦:比如 http://www.baidu.com?pageIndex=1&pageSize=10 中的
"?pageIndex=1&pageSize=10"就是QueryString
//传入键,得到值
function GetQueryStringValue(QueryString, key) { var value = ""; var sURL = QueryString; ///URL中是否包含查询字符串 if (sURL.indexOf("?") > 0) { //分解URL,第二的元素为完整的查询字符串 //即arrayParams[1]的值为【id=1&action=2】 var arrayParams = sURL.split("?"); //分解查询字符串 //arrayURLParams[0]的值为【id=1 】 //arrayURLParams[2]的值为【action=add】 var arrayURLParams = arrayParams[1].split("&"); //遍历分解后的键值对 for (var i = 0; i < arrayURLParams.length; i++) { //分解一个键值对 var sParam = arrayURLParams[i].split("="); if ((sParam[0] == key) && (sParam[1] != "")) { //找到匹配的的键,且值不为空 value = sParam[1]; break; } } } return value; }