C#--数据报表分页的实现汇总
以下是学习笔记:
效果如下:
通用分页的设计与实现
一、分页数据查询的原理分析
二、分页类的设计分析
总原则:提取不变的,封装变化的;不变的作为方法体,变化的作为参数
【变化的】
1.每页显示的条数
2.显示的字段(属性)
3.表的名称
4.查询条件
5.过滤的条件(主键或唯一键)
6.过滤的条数==================(需要计算的)
7.当前显示的页码
8.排序条件
9.记录总数===================(查询的结果返回)
10.显示的总页数================(查询结果返回后进一步运算得到)
【不变的】
查询语句的核心结构
【编写分页查询方法】
该查询方法不需要直接的参数传递,参数获取全部通过属性。
一、分页数据查询的原理分析
use DataPagerDB go --查询第一页 select Top 5 StudentId,StudentName,Gender,Birthday,PhoneNumber from Students where Birthday>'1989/10/12' --查询第二页 select Top 5 StudentId,StudentName,Gender,Birthday,PhoneNumber from Students where Birthday>'1989/10/12' and StudentId not in--不在下面的这个范围内的 (select Top 5 StudentId from Students where Birthday>'1989/10/12' order by StudentId ASC ) order by StudentId ASC --查询第三页 总结过滤条数=每页显示的条数*(显示的第几页-1) select Top 5 StudentId,StudentName,Gender,Birthday,PhoneNumber from Students where Birthday>'1989/10/12' and StudentId not in (select Top 10 StudentId from Students where Birthday>'1989/10/12' order by StudentId ASC ) order by StudentId ASC --查询符合条件的记录总数 select COUNT(*) from Students where Birthday>'1989/10/12' --计算符合条件的总页数(比如总计5条,每页分别显示:3、5、8,计算实际分页数) print '----相除----' print 5/3 --2页 print 5/5 --1页 print 5/8 --1页 print '---实际分页数---' print 5/3+1 --2页 print 5/5 --1页 print 5/8+1 --1页 --对于除不尽的情况,通过取模来判断(有余数的都加1,就是实际页数) print '---取模---' print 5%3 print 5%5 print 5%8 --==============分页实现的基本思路================= --每页显示的条数 --过滤掉的总数=每页显示的条数*(当前显示的页数-1) --查询条件的确定 --排序条件 --获取满足条件的记录总数 --知道查询结果需要显示的页数=记录总数/每页显示条数 + 1(如果记录总数和每页显示条数取模后不为0,则加1)
二,分页类的设计
提取不变的,封装变化的;不变的作为方法体,变化的作为参数
分页类的代码:SqlDataPager,实际开发应该放在DAL数据访问类库中的
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; namespace CSDataPager { /// <summary> /// 通用数据分页类 /// </summary> public class SqlDataPager { #region 一般属性 /// <summary> /// 每页显示的条数 /// </summary> public int PageSize { get; set; } /// <summary> /// 需要显示的字段(以逗号分隔 ) /// </summary> public string FiledName { get; set; } /// <summary> /// 表的名称 /// </summary> public string TableName { get; set; } /// <summary> /// 查询条件 /// </summary> public string Condition { get; set; } /// <summary> /// 表的主键或唯一键 /// </summary> public string PrimaryKey { get; set; } /// <summary> /// 当前页码 /// </summary> public int CurrentPage { get; set; } /// <summary> /// 排序条件 /// </summary> public string Sort { get; set; } #endregion #region 只读属性 /// <summary> /// 记录的总数【不能直接赋值】 /// </summary> // public int RecordCount { get; set; }//此中手设计不安全 private int recordCount; public int RecordCount//设置只读属性,外面不能直接赋值 { get { return recordCount; } } /// <summary> /// 总页数 /// </summary> public int TotalPages { get { if (recordCount != 0)//如果查询记录总数不为0 { if (recordCount % PageSize != 0) { return recordCount / PageSize + 1; } else { return recordCount / PageSize; } } else { this.CurrentPage = 1;//如果查询没有数据,则当前页码需要复位 return 0; } } } #endregion //分页查询方法所用的SQL语句 private string GetPagedSQL() { //计算需要过滤的总数 string filterCount = (PageSize * (CurrentPage - 1)).ToString(); //组合SQL语句 string sql = "select Top {0} {1} from {2} where {3} and {4} not in ";//0:每页显示的条数,1:字段,2:表名,3:where条件,, sql += "(select Top {5} {6} from {7} where {8} order by {9} ) order by {10};";//5:过滤的条数,6:主键,7:表名,8:where条件,9:排序的条件,10:排序的条件 sql += "select count(*) from {11} where {12}";//11:表名,12:where条件 查询满足条件的总数 sql = string.Format(sql, PageSize, FiledName, TableName, Condition, PrimaryKey, filterCount, PrimaryKey, TableName, Condition, Sort, Sort, TableName, Condition); return sql; } /// <summary> /// 执行分页查询,返回DataTable /// </summary> /// <returns></returns> public DataTable GetPagedData() { //【1】执行查询,返回分页后的结果集 DataSet ds = SQLHelper.GetDataSet(GetPagedSQL()); //【2】获取满足记录的总数 this.recordCount = Convert.ToInt32(ds.Tables[1].Rows[0][0]);//ds的第二张表的,第一行的,第一列 return ds.Tables[0]; } } }
三,分页UI的实现
public partial class FrmDataPager : Form { private SqlDataPager objPager = null; public FrmDataPager()//需要初始化的内容,要放在窗体的构造函数中 { InitializeComponent(); this.dtpBirthday.Text = "1988-1-1"; //初始化数据分页对象 objPager = new SqlDataPager() { PrimaryKey = "StudentId",//表的主键 TableName = "Students", FiledName = "StudentId,StudentName,Gender,Birthday,PhoneNumber", CurrentPage = 1, Sort = "StudentId ASC"//排序条件 }; //设置默认的显示条数 this.cboRecordList.SelectedIndex = 1; this.dgvStudentList.AutoGenerateColumns = false;//DataGridView自动生成列为禁止 //禁用相关按钮 this.btnFirst.Enabled = false; this.btnNext.Enabled = false; this.btnPre.Enabled = false; this.btnLast.Enabled = false; this.btnToPage.Enabled = false; } //执行查询的公共方法 private void Query() { //开启所有按钮 this.btnFirst.Enabled = true; this.btnNext.Enabled = true; this.btnPre.Enabled = true; this.btnLast.Enabled = true; this.btnToPage.Enabled = true; //【1】设置分页查询的条件 objPager.Condition = string.Format("Birthday>'{0}'", this.dtpBirthday.Text); //【2】设置每页显示的条数 objPager.PageSize = Convert.ToInt32(this.cboRecordList.Text.Trim()); //【3】执行查询 this.dgvStudentList.DataSource = objPager.GetPagedData(); //【4】显示记录总数、显示总页数、显示当前页码 this.lblRecordsCount.Text =objPager.RecordCount.ToString ();//总数 this.lblPageCount.Text = objPager.TotalPages.ToString();//总页数 if (this.lblPageCount.Text == "0")//如果总页数为0 { this.lblCurrentPage.Text = "0"; } else { this.lblCurrentPage.Text = objPager.CurrentPage.ToString();//当前页 } //禁用按钮的情况 if (this.lblPageCount.Text == "0" || this.lblPageCount.Text == "1") { this.btnFirst.Enabled = false; this.btnNext.Enabled = false; this.btnPre.Enabled = false; this.btnLast.Enabled = false; this.btnToPage.Enabled = false; } else { this.btnToPage.Enabled = true; } } //提交查询 private void btnQuery_Click(object sender, EventArgs e) { objPager.CurrentPage = 1;//每次执行查询都要设置为第1页 Query(); this.btnPre.Enabled = false;//上一页按钮 this.btnFirst.Enabled = false;//第一页按钮 } //第1页 private void btnFirst_Click(object sender, EventArgs e) { objPager.CurrentPage = 1; Query(); this.btnPre.Enabled = false; this.btnFirst.Enabled = false; // btnQuery_Click(null, null);//上面4行不写,可以直接调用上面的事件也是一样的 } //下一页 private void btnNext_Click(object sender, EventArgs e) { objPager.CurrentPage += 1; Query(); //当执行到最后一页的时候应该禁用最后一页和下一页的按钮 if (objPager.CurrentPage == objPager.TotalPages) { this.btnNext.Enabled = false; this.btnLast.Enabled = false; } } //上一页 private void btnPre_Click(object sender, EventArgs e) { objPager.CurrentPage -= 1; Query(); if (objPager.CurrentPage == 1)//如果是第一页 { this.btnPre.Enabled = false; this.btnFirst.Enabled = false; } } //最后一页 private void btnLast_Click(object sender, EventArgs e) { objPager.CurrentPage = objPager.TotalPages; Query(); this.btnNext.Enabled = false; this.btnLast.Enabled = false; } //跳转到 private void btnToPage_Click(object sender, EventArgs e) { if (this.txtToPage.Text.Trim().Length == 0)//如果没有输入 { MessageBox.Show("请输入要跳转的页码!","信息提示"); this.txtToPage.Focus(); return; } //使用正则表达式验证必须为大于0的正整数... int toPage = Convert.ToInt32(this.txtToPage.Text.Trim()); if (toPage > objPager.TotalPages) { MessageBox.Show("跳转的页数不能大于数据总页数!","信息提示"); this.txtToPage.Focus(); this.txtToPage.SelectAll();//让用户的输入内容全部选中,用户可以直接改啦 return; } //开始跳转页数 objPager.CurrentPage = toPage; Query(); if (objPager.CurrentPage == 1) { this.btnPre.Enabled = false; this.btnFirst.Enabled = false; } else if (objPager.CurrentPage == objPager.TotalPages) { this.btnNext.Enabled = false; this.btnLast.Enabled = false; } } //关闭窗口 private void btnClose_Click(object sender, EventArgs e) { this.Close(); } }