在上一节我们主要介绍了Asp.net常用的数据绑定控件,在谈到ListView控件时,我们说这是目前为止微软封装的功能最全的,最好用的数据绑定控件,ListView支持增、删、改、排序、分页,还可以自定义编写的模板格式显示数据。甚至如果你愿意,你不用写一行代码就可以实现数据的绑定,这个控件实在在太简单、太好用了。但是,我们要明白简单好用的东西是要付出代价的,没错,虽然ListView有这么多的优点,但是仍然无法掩盖它的性能劣势,因为它需要一下子加载所有的数据,显示在前台界面,同时会增加很多额外的东西增大服务器的压力,ListView支持分页,其分页功能的实现需要配合分页控件,它分页的原理是将所有的数据从服务器中一下子读出来,这样无疑增大的服务器的压力,有时候我们需要的仅仅是某一页的数据,但是内置的分页仍然会将所有的数据从数据库中加载进来。所以ListView内置的分页对于小数据量的数据还行,对于大量的数据则根本没法用。
这一节里我们主要带领大家实现ListView的高效分页。Repeater是一个拥有很好的扩展性的数据绑定控件,用户可以自定义显示格式,但不足之处在于它不支持分页,所以这一节里我也会向大家显示如何实现ListView的分页。
一、ListView高效分页
首先我们新建一个Asp.net Web项目在Default.aspx页拖放一个ListView控件,然后再拖放入一个ObjectDataSource作为数据源,页面布局如下:
下面我们需要为ObjectDataSource位置数据源,在此之前我们要需要新建一个强类型的数据集,然后将数据库中的Pserson表拖入数据集面板中,效果如下:
然后生成解决方案。这个时候就可以为ObjectDataSource设置数据源了,
设置的时候依次选择:选择业务对象里PsersonDSTableAdapters.PersonTableAdapter这一项,然后在下一步直接点击完成即可。
完成了数据源的配置,这个时候我们需要对ListView进行数据绑定,
如图示:
如果不想自定义的配置布局,可以点击配置ListView,这里边有已经布局好的方案,
如图示:
确定选用的布局之后页面呈现效果如下:
这个时候,我们已经实现了ListView的数据绑定展示,但是使用的分页是ListView内置的分页,根本不是我们要讲的分页,接下来才是我们要讲的核心。细心的朋友可能都会发现在上边生成强类型数据集PsersonDS中有两个额外的配置函数:如图示:
因此我们需要在添加两个函数
一、GetCount函数,步骤如下:
1、PsersonDS的PsersonTableAdapter点击右键添加查询
2、选择使用Sql语句,
3、选择Select(返回单个值),
4、直接下一步,然后为该函数起一个名字GetCount,即为获得数据库中信息的条数。
二、GetAll函数,步骤如下:
1、2步如上
3、选择Select(返回行)
4、写下如下Sql语句。SELECT * from(select PID, PName, PSex, PAge, PJob,Row_number() over(order by PID) as rownum FROM dbo.Pserson) T where T.rownum>@startRowIndex and T.rownum<@startRowIndex+@maximunRows
5、然后为该函数起名为GetAll
请大家注意红线标注的部分,这里边用到Sql server里的Row_number()排序函数,该函数在sql server2005以后才有的函数,数据编辑器不支持Row_Number()函数,所以创建完成后需要在GetPageData属性的parameters中添加两个参数,参数名必须是startRowIndex和maximumRows这两个,
添加步骤如下:在GetAll函数的属性Parameter中添加
startRowIndex和maximumRows这两个参数,参数类型为Int型,参数名必须为startRowIndex和maximumRows。在后边会给大家解释为什么必须是这两个。
添加完以后我们需要把当前的解决方案再生成一下,以便得到及时的更新。
如图:
前期的工作做好了,接下来需要我们在ListView中进行配置了,
先按照正常的步骤配置listview让ListView自动生成Template再修改ObjectDataSource的EnablePaging=“true”,然后SelectCountMethod设置为取得行数的方法即GetCount方法
设置selectMode为GetAll
如图示:
请大家注意红线标注的部分,我们这里启用了EnablePaging你可能会主要到这里边有两个属性MaximumRowsParameterName和StartRowIndexParameterName吧,仔细看一下它们是不是和之前我们在GetAll函数中添加的两个参数很像呢?没错,我们在GetAll里添加的两个参数就是为这两个属性赋值。
好了,到这里为止你已经实现了ListView的高效分页了,抓紧时间来体验下吧。同样对于GridView也可以用同样的方式实现高效分页,在这里就不多讲了。高效分页主要用到sql server中的Row_number() 函数,关于高效分页的Sql 语句还有很多,有兴趣的朋友可以参看我之前总结的文章《SQL语句全解析》,那里边有对分页的专门介绍,希望可以对大家有所帮助,还请多多指点!
二、Repeater高效分页
Repeater是一个扩展性很好的控件,用户可以自定义其要展示的内容格式,但是美中不足的是它不支持分页、排序、编辑,仅提供重复模板内容,在实际运用中,我们大多用其来展示数据,但是如果数据量过大的时,这个时候就需要进行分页处理,在本节里,我会带领大家做一个Repeater的分页处理。
首先新建一个.aspx页在上面放置一个Repeater控件,页面布局如下:
<div> <h1>Repeater分¤?页°3</h1> <asp:Repeater ID= "Repeater1" runat= "server" > <FooterTemplate> </table> </FooterTemplate> <ItemTemplate> <tr> <td><asp:Label ID= "Label1" runat= "server" Text= '<%#Eval("PName") %>' ></asp:Label></td> <td><asp:Label ID= "Label2" runat= "server" Text= '<%#Eval("PAge") %>' ></asp:Label></td> <td><asp:Label ID= "Label3" runat= "server" Text= '<%#Eval("PSex") %>' ></asp:Label></td> <td><asp:Label ID= "Label4" runat= "server" Text= '<%#Eval("PJob") %>' ></asp:Label></td> </tr> </ItemTemplate> <HeaderTemplate> <table><tr><th>姓?名?</th><th>年¨º龄¢?</th><th>性?别Àe</th><th>工¡è作Á¡Â</th></tr> </HeaderTemplate> </asp:Repeater> <div id= "fenye" > <asp:Label ID= "lbNow" runat= "server" Text= "当Ì¡À前¡ã页°3:êo" ></asp:Label> <asp:Label ID= "lbPage" runat= "server" Text= "1" ></asp:Label> <asp:Label ID= "lbAll" runat= "server" Text= "总Á¨¹页°3数ºy:êo" ></asp:Label> <asp:Label ID= "lbCount" runat= "server" Text= "" ></asp:Label> <asp:LinkButton ID= "lbtnFirst" runat= "server" onclick= "lbtnFirst_Click" >首º¡Á页°3</asp:LinkButton> <asp:LinkButton ID= "lbtnUp" runat= "server" onclick= "lbtnUp_Click" >上¦?一°?页°3</asp:LinkButton> <asp:LinkButton ID= "lbtnDown" runat= "server" onclick= "lbtnDown_Click" >下?一°?页°3</asp:LinkButton> <asp:LinkButton ID= "lbtnLast" runat= "server" onclick= "lbtnLast_Click" >尾2页°3</asp:LinkButton> <asp:DropDownList ID= "DropDownList1" runat= "server" Width= "80px" > </asp:DropDownList> <asp:LinkButton ID= "lbtnGo" runat= "server" BackColor= "LightBlue" BorderWidth= "2px" BorderColor= "Blue" onclick= "lbtnGo_Click" style= "width: 20px" >Go</asp:LinkButton> </div> <br /> </div> |
页面布局如下:
由页面布局可知,我们分别放置了四个LinkButton按钮作为前后的导航,一个DropDownList文本框和一个button按钮作为*导航。
在.cs页处理如下:
先新建一个全局的SqlConnection对象并实例化,然后新建一个SqlCommand对象
SqlConnection new SqlConnection(ConfigurationManager.ConnectionStrings[ "LinqTestConnectionString" ].ToString()); public SqlCommand sqlCmd= null ; |
然后我们需要定义一个DropListBind()函数,在首次进入页面时为DropDownList赋值
代码如下:
public void DropListBind() { sqlConn.Open(); sqlCmd = new SqlCommand( "select count(*) from Pserson" , sqlConn); //获取数据库中信息的总条数 this .lbCount.Text = (Convert.ToInt32(sqlCmd.ExecuteScalar())/15).ToString(); //每页显示15条,算出总页数,并为DropDownList赋值 int [] num = new int [Convert.ToInt32(lbCount.Text)]; for ( int i = 1; i <= Convert.ToInt32(lbCount.Text); i++) { num[i - 1] = i; } DropDownList1.DataSource = num; DropDownList1.DataBind(); } |
接下来需要再创建一个函数用来管理首页、上一页、下一页、尾页四个按钮的使用状态
代码如下:
public void State() { if (lbPage.Text == "1" ) //如果当前页为第一页,则前一页和首页按钮禁用 { lbtnFirst.Enabled = false ; lbtnUp.Enabled = false ; lbtnLast.Enabled = true ; lbtnDown.Enabled = true ; } if (lbPage.Text == lbCount.Text) //如果当前页为最后一页,则后一页和尾页按钮禁用 { lbtnFirst.Enabled = true ; lbtnUp.Enabled = true ; lbtnLast.Enabled = false ; lbtnDown.Enabled = false ; } if (Convert.ToInt32(lbPage.Text) > 1 && Convert.ToInt32(lbPage.Text) < Convert.ToInt32(lbCount.Text))<br> //如果当前也在首页和尾页之间则四个按钮均可用 { lbtnFirst.Enabled = true ; lbtnUp.Enabled = true ; lbtnLast.Enabled = true ; lbtnDown.Enabled = true ; } } |
然后,我们开始创建展示数据的函数,该函数的作用在于当用户点击按钮时从数据库中读取不同的数据信息,和ListView内置的分页效果不同,每次用户点击时,并不是一下子从数据库加载所有的数据信息而是仅加载请求的那一页的数据信息,这样整个查询的效率会相当高,服务器的压力也会相对减小。
代码如下:
public void Show() { sqlCmd = new SqlCommand( "select * from Pserson where PID>'" + (Convert.ToInt32(lbPage.Text)-1)*15 <br>+ "' and PID<='" + Convert.ToInt32(lbPage.Text)*15 + "' order by PID ASC" , sqlConn);<br> //从数据库中筛选信息,仅加载当前请求的那一页的信息,效率会相对比较高,并非全部加载 SqlDataAdapter sAdapter = new SqlDataAdapter(sqlCmd); DataSet ds = new DataSet(); sAdapter.Fill(ds, "Result" ); sqlConn.Close(); Repeater1.DataSource = ds.Tables[ "Result" ]; Repeater1.DataBind(); } |
做完这些准备工作之后,我们就要在Page_Load函数里边做一些初始化的操作
代码如下:
protected void Page_Load( object sender, EventArgs e) { if (!IsPostBack) { DropListBind(); //为DropDownList赋值 Show(); //初始化显示第一页,默认当前为第一页 State(); //初始化导航按钮的使用状态 } } |
接下来我们需要对四个导航按钮做不同的处理,以便实现用户的操作。
//首页,只需将当前页设置为1即可
protected void lbtnFirst_Click( object sender, EventArgs e) { lbPage.Text = "1" ; Show(); State(); } |
//前一页,将当前页的值减去一然后再赋值为当前页即可
protected void lbtnUp_Click( object sender, EventArgs e) { lbPage.Text = (Convert.ToInt32(lbPage.Text) - 1).ToString(); Show(); State(); } |
//后一页,将当前页的值加上一然后再赋值为当前页即可
protected void lbtnDown_Click( object sender, EventArgs e) { lbPage.Text = (Convert.ToInt32(lbPage.Text) +1).ToString(); Show(); State(); } |
//尾页,将当前页的值赋值为总页数即可
protected void lbtnLast_Click( object sender, EventArgs e) { lbPage.Text =lbCount.Text; Show(); State(); } |
//将当前页的值赋值为DropDownList1所选值即可
protected void lbtnGo_Click( object sender, EventArgs e) { lbPage.Text = DropDownList1.SelectedValue; Show(); State(); } |
好了,到这里我们已经实现了Repeater的高效分页,因为只是一个演示的demo所以这里没有用到存储过程将这个查询分页语句进行封装,在实际的开发过程中,我们应该专门写一个存储过程用来分页。在这里我也写了一个小的分页方法供大家参考,这个方法主要是和本示例相搭配的。具体如下:
Create ( @curPage int , @pageSize int ) AS select PName,PSex,PAge,PJob from Pserson where PID>(@curPage-1)*@pageSize and PID<@curPage*@pageSize order by PID ASC |
我们通过实现Repeater的分页,不难发现,其实我们完全可以把分页做成一个用户自定义的控件,来帮我们实现分页。参照之前一个朋友的思路,我已经初步的实现了一个用户自定义的分页控件。还在完善后,后续会分享给大家。
这一节的学习就到这里了,希望能对大家有所帮助,还请多多指点!