在ASP.NET编程中,我们常常会使用到列表数据,但由于网页的大小限制,常常有分页的需求,手动分页是很痛苦的,从SQL语句到排版,控制页数,控制跳转,控制这控制那。烦的狠,下面给大家介绍一种可以自动计算出分页并一行代码生成页脚的DLL。
IDE:vs2012语言:C# 项目类型:ASP.NET MVC4 WEB应用程序
拿一个我做的书店的系统为例,采用的是三层架构,另加通用和实体两个程序集。首先要在你的web层添加引用,引用这个MvcPager.DLL,然后顺便把那个pagerstyles.css拷贝到你的项目的装css的文件夹下,最后一步,在web.config中中添加一个命名空间,省得用一次就要前面加上命名空间,这样一次解决。没记错就只这样添加的,如果有错误,就去看看那个dll的命名空间
下面就要使用这个玩意了。
还是拿我做的书店来举例。我要做一个图书列表页,那么来装这个图书列表的数据就是一个实体,首先在实体层建立两个类,一个是BookEntity,对应的是MSSQL中的books表中的各个字段。还有一个是BookPageInfoEntity,其中设置了四个属性,分别是TotalCount,PageCount,PageIndex,BookList,前三个都是整形的,都是int类型的,最后一个是一个图书列表,数据类型是List,装了一大堆的书。实体类建好之后,就要开始写控制器了。在Book控制器里定义一个BookManager的动作方法,下面只列出拿到这个图书列表数据的关键代码。建一个名字叫BookList的视图,采用Razor的视图引擎,不用母板,一切从简。。视图中先声明模型(强类型)@model PagedList(这个PagedList就是MvcPager中的一个类,其中放的是你要展示的类型,即我们BookEntity,而不是BookPageInfoEntity),然后判断一下
如果Model不是空,就可以使用了,不然会报空指针异常。PageList是继承List的,所以只要判断Count属性大于0就不是空的了。然后在视图中展示的代码就可以省略了吧。你想怎么写都可以了,Model.Title什么的都上吧。骚等,另起一段,喝口水。
下面就是比较关键的取数据的阶段了。首先要清楚我们取的是什么数据,既然是分页,就要不光取出来Book的一个集合,还要附带总数,页大小,页索引等信息,那就要先定义一个BookPageInfoEntity的实例,然后通过查数据库,把这个实例填满数据。然后就定义一个PageListresult = new PageList(a,b,c,d);他需要四个参数,
public PagedList(IEnumerable currentPageItems, int pageIndex,int pageSize, int totalItemCount);
public PagedList(IQueryable currentPageItems, intpageIndex, int pageSize, int totalItemCount);
这是其中的两个构造器的原型,第一个是要一个数据集,实现了IEnumerable或者IQueryable的接口,第二个要页索引,第三个要页大小,第四个参数要一个总数。到这里,就算把数据取出来了。然后把result返回给视图就好了。
从头撸一遍过程:
BookPageInfoEntity booklist = new BookPageInfoEntity();
booklist = BookBLL.QueryBookListWithPage(pageIndex, pageSize,searchType,key);
ViewBag.SearchType = searchType;
ViewBag.SearchKey = key;
PagedList result = new PagedList(booklist.BookList, pageIndex,pageSize, booklist.TotalCount);
return View("BookList", "_LayoutPage1",result);
其中ViewBag那两句不用管,是记录搜索的关键字和搜索的类型的。
视图声明的代码:(在BookList.cshtml中)
@model PagedList
@section Script{
@{
Html.RegisterMvcPagerScriptResource();
}
}
列一段界面展示的代码:
@for (int i = 0; i < Model.Count; i++)
{
}
(@model PagedList声明之后,在其他部分,Model就可以代替PagedList了)
sorry,忘记了,这个Script的部分是要放在母板页中注册的,如果木有模板页,就放在本页注册。抱歉抱歉。
然后是一键生成页脚的:(真是超方便,都封装好了。)
@Html.Pager(Model, new PagerOptions
{
ShowPageIndexBox = true,
PageIndexBoxType = PageIndexBoxType.DropDownList,
ShowGoButton = false,
AutoHide = false,
NumericPagerItemCount = 5
},
new { id = "menepager" })
下面介绍说一下查数据的方法。
我是通过三层调用的,BLL层几乎没写啥。贴一下DAL层的代码。(BLL层就是直接参数拿过来直接跳到DAL,还是贴一下代码吧。就一行
public static BookPageInfoEntity QueryBookListWithPage(intpageIndex, int pageSize, string searchType,string key)
{
return BookDAL.QueryBookListWithPage(pageSize, pageIndex,searchType,key);
})
下面这个就很重要了,是DAL层中的代码:
public static BookPageInfoEntity QueryBookListWithPage(intpageSize, int pageIndex, string searchType,string key)
{
string sql = @"SELECT @totalCount = COUNT(*)
FROM dbo.Books AS b
INNER JOIN dbo.Publishers AS p ON PublisherId = p.Id
WHERE 1 = 1 #condition#
SELECT TOP ( @pageSize)
*
FROM (SELECT ROW_NUMBER() OVER ( ORDER BY b.Id ) AS RowId ,
b.Id,
b.Title ,
p.Name,
b.Author,
b.ContentDescription
FROM dbo.Books AS b
INNER JOIN dbo.Publishers AS p ON PublisherId = p.Id
INNER JOIN dbo.Categories AS c ON CategoryId = c.Id
WHERE 1 = 1 #condition#
) AS A
WHERE A.RowId > @pageSize * @pageIndex";
List paras = new List();
paras.Add(new SqlParameter("@pageSize", pageSize));
paras.Add(new SqlParameter("@pageIndex", pageIndex - 1));
paras.Add(new SqlParameter("@totalCount", 0));
paras.Direction = ParameterDirection.Output;
int totalCount = 0;
if (string.IsNullOrEmpty(searchType))
{
sql = sql.Replace("#condition#", "");
}
else
{
sql = sql.Replace("#condition#", string.Format(" and {0} like'%{1}%'", searchType,key));
}
DataTable dt = DbManager.ExcuteDataWithPage(sql, ref totalCount,paras.ToArray());
List booklist = null;
if (dt.Rows.Count > 0)
{
booklist = ConvertHelper.ConvertToList(dt);
return new BookPageInfoEntity
{
TotalCount = totalCount,
BookList = booklist
};
}
else
{
return null;
}
}
- 这个比较重要,就列个表说说。
- 首先看SQL语句,上半部分是查总数的,这个应该没问题
- 下半部分是分页的,利用T-SQL中的ROW_NUMBER()函数来分页,它后面那个OVER ( ORDER BY b.Id)是排序的字段,如果有按什么排序的选择框的话,就可以传个参数进来。
- 剩下的就是正常的分页的SQL写法了。
- 一共有三个参数,所以定义SqlParameter[]和List都是ok的。
- 其中@totalCount是个输出参数,要设置一下它的Direction为ParameterDirection.Output;
- 如果有搜索条件传进来要把#condition#替换掉,没有就替换成空字符串
- 然后定义个数据表对象,把sql和TotalCount还有参数列表都传入ExcuteDataWithPage中
- ok,拿到的是一个装了带有好多BookEntity的和总数的DataTable对象。
- 下面是需要把DataTable对象转化成List集合,我调用了一个利用泛型和反射写的转化类,如果不用这个,也可以用for循环或者foreach循环来写,都是OK的。
- 转换之后就可以返回给BLL了,给一个BookPageListentity的对象也行,给一个匿名类也可以,不过如果返回一个匿名类的话,就要把函数的类型改成dynamic,怎么做随你了。
就剩下最后一个问题了,ExcuteDataWithPage方法,这个也是我自定义的。不过这个就要跟数据库接触了。先贴代码:
public static DataTable ExcuteDataWithPage(string sql,ref inttotalCount,params SqlParameter[] paras)
{
using (SqlConnection con = new SqlConnection(Constr))
{
SqlDataAdapter dap = new SqlDataAdapter(sql, con);
DataTable dt = new DataTable();
dap.SelectCommand.Parameters.AddRange(paras);
dap.Fill(dt);
SqlParameter ttc =dap.SelectCommand.Parameters["@totalCount"];
if (ttc!=null)
{
totalCount = Convert.ToInt32(ttc.Value);
}
return dt;
}
}
- 首先看参数,有三个,第一个是sql语句,第二个是一个根据业务需要传入的TotalCount,因为int是值类型,所以这里打上ref标记,第三个是SqlParameter[],可变长度的。
- 先using一个Sqlconnection对象,然后就可以不用去关闭了,用完了系统会自动给你关闭。
- 在using内部定义个SqlDataAdapter dap = new SqlDataAdapter(sql,con),把sql语句和Sqlconnection对象给SqlDataAdapter,这个是数据适配器,这里也可以用SqlCommand对象,看读者喜好了。
- 然后把SqlParameter[]赋值给SqlDataAdapter的SelectCommand集合的Parameters集合,用集合通用的方法AddRange或者Add(dap.SelectCommand.Parameters.AddRange(paras);)
- 接下来就是很正常的定义个DataTale并且填充到SqlDataAdapter 中了。
- 这步也很关键,把@totalCount参数从参数集合中取出来,集合通用的方法,用索引器取。SqlParameter ttc =dap.SelectCommand.Parameters["@totalCount"];
- 再把tcc转化成int就大功告成了。
ok,测试一下我们的效果吧!!!是不是感觉很麻烦,不过据说是利于维护,所以就麻烦一次吧,第二次写就不会这么麻烦了。贴图。。。
看那个页脚,唉界面太丑了。凑合看吧,效果大概就这么个效果
@Model
![[i] [i]](https://i-blog.csdnimg.cn/blog_migrate/ea23611721b17d53b3b2f1bb3e19c1b9.gif)
![[i] [i]](https://i-blog.csdnimg.cn/blog_migrate/ea23611721b17d53b3b2f1bb3e19c1b9.gif)
![[i] [i]](https://i-blog.csdnimg.cn/blog_migrate/ea23611721b17d53b3b2f1bb3e19c1b9.gif)
编辑