WinForm轻松实现自定义分页 (转载)
转载至http://xuzhihong1987.blog.163.com/blog/static/267315872011315114240140/
以前都是做web开发,最近接触了下WinForm,发现WinForm分页控件好像都没有,网上搜索了一下,发现有很多网友写的分页控件,分页效果应该都能实现吧,只是其风格都不是很符合我想要的。做web的时候,我习惯了Extjs的Grid分页效果,所以也想在WinForm中做个类似的效果,所以咬咬牙,做个山寨版本的吧,虽然自己写费时费力,在项目进度考虑中不是很可取,但是还是特别想山寨一回,做自己喜欢的风格。
按照惯例,还是先看看实现效果图吧(有图有真像,才好继续下文呀)
应用效果:(效果有点难看,因为我是刚装的
xp系统,还是经典主题,如果换成Win7系统或其他主题,效果还是会很不错的)
我们要做的就是上图显示的一个自定义控件,这个效果参考自我做
web开发使用的Extjs之Grid的分页效果(如下图)
Extjs的动画效果我们暂时就不实现了,这里只做个外观看起来想像即可,完全一样就脱离“山寨”概念了,总要比人家差点吧,谁让咱是模仿呢!
言归正传,我们现在就看看具体怎么实现吧:
第一步:先布局
注:我们创建的是用户自定义控件,而不是WinForm窗体
就是先做出个显示效果,这个布局很简单,在这就不多说,重点就是“首页、前一页、后一页、末页”图标,每个图标分两种,一是能点击的高亮效果,一个是灰色不不能点击。以下是套图:(大家如果不喜欢,可以去做成自己喜欢的风格图片)
第二步:编写分页代码
布局好了,那么第二步我们就要代码实现正确显示文字信息,分页事件,每页条数选择事件,公开属性和事件。以下是完整代码:
/// <summary>
/// 声明委托
/// </summary>
/// <param name="e"></param>
public delegate void EventPagingHandler(EventArgs e);
public partial class Paging : UserControl
{
public Paging()
{
InitializeComponent();
}
public event EventPagingHandler EventPaging;
#region 公开属性
private int _pageSize = ;
/// <summary>
/// 每页显示记录数(默认50)
/// </summary>
public int PageSize
{
get
{
return _pageSize;
}
set
{
if (value > )
{
_pageSize = value;
}
else
{
_pageSize = ;
}
this.comboPageSize.Text = _pageSize.ToString();
}
}
private int _currentPage = ;
/// <summary>
/// 当前页
/// </summary>
public int CurrentPage
{
get
{
return _currentPage;
}
set
{
if (value > )
{
_currentPage = value;
}
else
{
_currentPage = ;
}
}
}
private int _totalCount = ;
/// <summary>
/// 总记录数
/// </summary>
public int TotalCount
{
get
{
return _totalCount;
}
set
{
if (value>=)
{
_totalCount = value;
}
else
{
_totalCount = ;
}
this.lblTotalCount.Text = this._totalCount.ToString();
CalculatePageCount();
this.lblRecordRegion.Text = GetRecordRegion();
}
}
private int _pageCount = ;
/// <summary>
/// 页数
/// </summary>
public int PageCount
{
get
{
return _pageCount;
}
set
{
if (value>=)
{
_pageCount = value;
}
else
{
_pageCount = ;
}
this.lblPageCount.Text = _pageCount + "";
}
}
#endregion
/// <summary>
/// 计算页数
/// </summary>
private void CalculatePageCount()
{
if (this.TotalCount>)
{
this.PageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(this.TotalCount) / Convert.ToDouble(this.PageSize)));
}
else
{
this.PageCount = ;
}
}
/// <summary>
/// 获取显示记录区间(格式如:1-50)
/// </summary>
/// <returns></returns>
private string GetRecordRegion()
{
if (this.PageCount == ) //只有一页
{
return "1-" + this.TotalCount.ToString();
}
else //有多页
{
if(this.CurrentPage==) //当前显示为第一页
{
return "1-"+this.PageSize;
}
else if(this.CurrentPage==this.PageCount) //当前显示为最后一页
{
return ((this.CurrentPage-)*this.PageSize+) +"-"+this.TotalCount;
}
else //中间页
{
return ((this.CurrentPage-) * this.PageSize+) + "-" + this.CurrentPage * this.PageSize;
}
}
}
/// <summary>
/// 数据绑定
/// </summary>
public void Bind()
{
if (this.EventPaging != null)
{
this.EventPaging(new EventArgs());
}
if (this.CurrentPage>this.PageCount)
{
this.CurrentPage = this.PageCount;
}
this.txtBoxCurPage.Text = this.CurrentPage+"";
this.lblTotalCount.Text = this.TotalCount+"";
this.lblPageCount.Text = this.PageCount+"";
this.lblRecordRegion.Text = GetRecordRegion();
if (this.CurrentPage==)
{
this.btnFirst.Enabled = false;
this.btnPrev.Enabled = false;
this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled;
}
else
{
this.btnFirst.Enabled = true;
this.btnPrev.Enabled = true;
this.btnFirst.Image = global::CHVM.Properties.Resources.page_first;
this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev;
}
if (this.CurrentPage == this.PageCount)
{
this.btnNext.Enabled = false;
this.btnLast.Enabled = false;
this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled;
this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled;
}
else
{
this.btnNext.Enabled = true;
this.btnLast.Enabled = true;
this.btnNext.Image = global::CHVM.Properties.Resources.page_next;
this.btnLast.Image = global::CHVM.Properties.Resources.page_last;
}
if (this.TotalCount==)
{
this.btnFirst.Enabled = false;
this.btnPrev.Enabled = false;
this.btnNext.Enabled = false;
this.btnLast.Enabled = false;
this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled;
this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled;
this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled;
}
}
private void btnFirst_Click(object sender, EventArgs e)
{
this.CurrentPage = ;
this.Bind();
}
private void btnPrev_Click(object sender, EventArgs e)
{
this.CurrentPage -= ;
this.Bind();
}
private void btnNext_Click(object sender, EventArgs e)
{
this.CurrentPage += ;
this.Bind();
}
private void btnLast_Click(object sender, EventArgs e)
{
this.CurrentPage = this.PageCount;
this.Bind();
}
/// <summary>
/// 改变每页条数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comboPageSize_SelectedIndexChanged(object sender, EventArgs e)
{
this.PageSize = Convert.ToInt32(comboPageSize.Text);
this.Bind();
}
}
这里重点提两点:一是图片切换:
this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
Image对象是在Properties.Resource.resx中自动生成的,代码如下:
internal static System.Drawing.Bitmap page_first {
get {
object obj = ResourceManager.GetObject("page-first", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap page_first_disabled {
get {
object obj = ResourceManager.GetObject("page_first_disabled", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
二是应用了委托事件:我们在这定义了一个分页事件
public event EventPagingHandler EventPaging;
在数据绑定方法中实现它:
/// <summary>
/// 数据绑定
/// </summary>
public void Bind()
{
if (this.EventPaging != null)
{
this.EventPaging(new EventArgs());
}
//… 以下省略
}
这里需要大家对C#的委托和事件有一定的了解,不清楚的可以直接使用,或者先去查阅相关参考资料,这里我们就不谈委托机制了。
第三步:应用
值得一提的是,WinForm并不能直接把用户自定控件往Windows窗体中拖拽,而自动生成实例(ASP.NET是可以直接拖拽的)。那么如果我们需要在应用中使用,只能自己修改Desginer.cs代码了。
先声明:
private CHVM.PagingControl.Paging paging1;
然后在InitializeComponent()方法中实例化:
this.paging1 = new CHVM.PagingControl.Paging();
//
// paging1
//
this.paging1.CurrentPage = ;
this.paging1.Location = new System.Drawing.Point(, );
this.paging1.Name = "paging1";
this.paging1.PageCount = ;
this.paging1.PageSize = ;
this.paging1.Size = new System.Drawing.Size(, );
this.paging1.TabIndex = ;
this.paging1.TotalCount = ;
//在这里注册事件
this.paging1.EventPaging += new CHVM.PagingControl.EventPagingHandler(this.paging1_EventPaging);
加完后就能看到效果了,相当于托了一个分页控件的效果:(如下图所示)
最后在事件中加入分页事件需要执行的代码:
/// <summary>
/// 分页事件
/// </summary>
/// <param name="e"></param>
private void paging1_EventPaging(EventArgs e)
{
GvDataBind(); //DataGridView数据绑定
}
/// <summary>
/// 查询
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnQuery_Click(object sender, EventArgs e)
{
paging1_EventPaging(e);
}
/// <summary>
/// gvOperateLogList 数据邦定
/// </summary>
private void GvDataBind()
{
PagingCondition paging = new PagingCondition()
{
startIndex=paging1.CurrentPage,
pageSize = paging1.PageSize
};
MultiCondition condition = new MultiCondition();
condition.DateSign="FOperateTime";
condition.BeginDate = dtBegin.Value;
condition.EndDate = dtEnd.Value;
if (comboOperator.Text != "")
{
condition.Dict.Add("FOperator", comboOperator.Text);
}
if (comboType.Text != "")
{
condition.Dict.Add("FType", comboType.Text);
}
if (comboObject.Text != "")
{
condition.Dict.Add("FOptObject", comboObject.Text);
}
if (txtBoxContent.Text != "")
{
condition.Dict.Add("FContent", txtBoxContent.Text);
}
DataTable dt = GetByCondition(paging, condition);
paging1.TotalCount = Convert.ToInt32(dt.TableName);
gvOperateLogList.DataSource = dt;
gvOperateLogList.Columns.Clear();
var dict = GetGvColumnsDict();
DataGridViewHelp.DisplayColList(gvOperateLogList, dict);
}
注:MultiCondition、PagingCondition是我专门针对分页综合查询定义的两个类,兴趣的话可以去了解一下:
查询条件就统一定义在MultiCondition中(详见:http://xuzhihong1987.blog.163.com/blog/static/267315872011294150763 ),
PagingCondition是分页条件(详见: http://xuzhihong1987.blog.163.com/blog/static/2673158720112941950801 ),
Extjs+LINQ轻松实现高级综合查询:
http://xuzhihong1987.blog.163.com/blog/static/2673158720112943356111/
其他:
/// <summary>
/// gv显示列设置
/// </summary>
/// <returns></returns>
public Dictionary<string, string> GetGvColumnsDict()
{
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("FTYPE", "操作类型");
dict.Add("FOPTOBJECT", "操作对象");
dict.Add("FCONTENT", "操作内容");
dict.Add("FOperator", "操作人员");
return dict;
}
DataGridViewHelp.DisplayColList是一个静态方法,为一个辅助类:
/// <summary>
/// 替换列表
/// </summary>
/// <param name="dgv">类表名称</param>
/// <param name="dic">数据</param>
/// <param name="isRM">是否显示序列号</param>
public static void DisplayColList(DataGridView dgv, Dictionary<string, string> dic)//, bool isRM
{
_dgv = dgv;
dgv.RowsDefaultCellStyle.BackColor = Color.FromArgb(, , );//第一行
dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(, , );//第二行
dgv.GridColor = Color.FromArgb(, , );//
dgv.RowTemplate.Height = ;//列宽
dgv.AllowUserToAddRows=false;//无空行
dgv.CellBorderStyle = DataGridViewCellBorderStyle.SingleVertical;
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.AllowUserToOrderColumns = true;
dgv.RowPostPaint += new DataGridViewRowPostPaintEventHandler(dgv_RowPostPaint);
dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);//列头样式
dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);//选中行样式
foreach (KeyValuePair<string, string> cl in dic)
{
dgv.AutoGenerateColumns = false;
DataGridViewTextBoxColumn obj = new DataGridViewTextBoxColumn();
obj.DataPropertyName = cl.Key;
obj.HeaderText = cl.Value;
obj.Name = cl.Key;
obj.Width = ;
//obj.DefaultCellStyle.Padding.All = 10;
obj.Resizable = DataGridViewTriState.True;
dgv.Columns.AddRange(new DataGridViewColumn[] { obj });
}
}
到此实现就全部完成了,运行效果后就是前面所示的效果!也可以动态修改每页条数。
说在最后,改功能简单是简单,但是涉及到很多知识点,委托、事件、
DataGridView数据动态绑定,综合查询,我这里用的是Oracle数据库,如果用LINQ语法的话查询数据会比较方便,写起代码也会显得很优雅。
/// <summary> /// 获取条件查询数据 /// </summary> /// <param name="paging"></param> /// <param name="conditon"></param> /// <returns></returns> private DataTable GetByCondition(PagingCondition paging, MultiCondition conditon) { string strSql = "select * from TOperateLog "; string strSqlGetCount = "select count(1) from TOperateLog "; string strWhere = " where 1=1 "; if (conditon != null) { if (conditon.DateSign == "FOperateTime") //操作日期 { if (conditon.BeginDate != DateTime.MinValue) { strWhere += string.Format(" and FOperateTime>='{0}'", conditon.BeginDate.ToString("yyyy-MM-dd HH:mm:ss")); } if (conditon.EndDate != DateTime.MaxValue) { strWhere += string.Format(" and FOperateTime<='{0}'", conditon.EndDate.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss")); } } var dict = conditon.Dict; if (dict != null) { foreach (var key in dict.Keys) { if (key.Equals("FType")) //操作类型 { strWhere += string.Format(" and FType='{0}'", dict[key]); } if (key.Equals("FOperator")) //操作人员 { strWhere += string.Format(" and FOperator='{0}'", dict[key]); } else if (key.Equals("FOptObject")) //操作对象 { strWhere += string.Format(" and FOptObject='{0}'", dict[key]); } else if (key.Equals("FContent")) //操作内容 { strWhere += string.Format(" and FContent like '%{0}%'", dict[key]); } } } } strWhere += " order by FOperateTime "; strSql += strWhere; strSqlGetCount += strWhere; if (paging != null) { if (paging.needPaging) { //strSql = string.Format("select * from ( {0} ) where ROWNUM>={1} and ROWNUM<={2}", strSql, paging.startIndex, paging.startIndex + paging.pageSize-1); strSql = string.Format("select * from (select T.*,RowNum RN from ({0})T where ROWNUM <={1}) where RN>={2} ",strSql, paging.startIndex + paging.pageSize - 1,paging.startIndex); } } DataTable dt = DataCon.Query(strSql).Tables[0]; dt.TableName = DataCon.GetSingle(strSqlGetCount)+""; return dt; }
WinForm轻松实现自定义分页 (转载)的更多相关文章
- winform中DataGridView实现分页功能
WinForm轻松实现自定义分页 (转载) WinForm轻松实现自定义分页 (转载) 转载至http://xuzhihong1987.blog.163.com/blog/static/26731 ...
- C# DataGridView自定义分页控件
好些日子不仔细写C#代码了,现在主要是Java项目,C#.Net相关项目不多了,有点手生了,以下代码不足之处望各位提出建议和批评. 近日闲来无事想研究一下自定义控件,虽然之前也看过,那也仅限于皮毛,粗 ...
- 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义分页
jQuery EasyUI 数据网格 - 自定义分页 数据网格(datagrid)内置一个很好特性的分页功能,自定义也相当简单.在本教程中,我们将创建一个数据网格(datagrid),并在分页工具栏上 ...
- Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)
Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...
- asp.net webform 自定义分页控件
做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: & ...
- Python之路【第十九篇】自定义分页实现(模块化)
自定义分页 1.目的&环境准备 目的把分页写成一个模块的方式然后在需要分页的地方直接调用模块就行了. 环境准备Django中生成一个APP并且注册,配置URL&Views 配置URL ...
- MVC下分页的自定义分页一种实现
1.引言 在MVC开发中我们经常会对数据进行分页的展示.通过分页我们可以从服务端获取指定的数据来进行展示.这样既节约了数据库查询的时间也节约了网络传输的数据量.在MVC开发中使用的比较多的应该是MVC ...
- Django自定义分页、bottle、Flask
一.使用django实现之定义分页 1.自定义分页在django模板语言中,通过a标签实现; 2.前段a标签使用<a href="/user_list/?page=1"> ...
- Mvc自定义分页控件
MVC开发分页常常使用第三方控件,生成的分页HTML带有版权申明,虽然免费,但是总有的别扭.于是,某日,楼主闲来蛋疼,折腾了个自定义分页控件: 先来展示下效果图: 1>当分页不超过10页的时候, ...
随机推荐
- hadoop2.7.1安装
Hadoop2.7.1安装与配置 http://www.oschina.net/question/117352_247251 http://www.cnblogs.com/wayne1017/arch ...
- eclipse无法自动识别出svn项目
因为重新安装了svn插件,重启后发现原来的svn项目无法自动识别出来,连Team->Share Project都没有,而本地用tortoiseSvn是可以正常操作的. 后来我把项目删除然后重新导 ...
- java系列-安装MySql(三)
第一大步:MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英文提示),一般MySQL将会安装 ...
- MVC后台传dt数据
//MVC后台传dt数据 public JsonResult TeacherVoteInfo([FromBody]Teacher_VoteModel model) { string tname = m ...
- CentOS-6.5安装zabbix2.4.4
使用epel源 (检查网络连接是否正常) //这里使用epel源 [root@localhost /]# wget -O /etc/yum.repos.d/CentOS-Base.repo ht ...
- CSS3实现背景颜色渐变 摘抄
一. Webkit浏览器 (1) 第一种写法: background:-webkit-gradient(linear ,10% 10%,100% 100%, color-stop(0.14,rgb(2 ...
- (一)css代码积累——自己经常忘记,但是总记不住的代码
1.透明度设置 90%透明:filter:alpha(opacity=90);-moz-opacity:0.90;-khtml-opacity: 0.90;opacity: 0.90; 80%透明:f ...
- 简单易懂的crontab设置工具集
导读 在上一篇文章中,我介绍了crontab的配置文件以及如何设置定时任务,对于偶尔用一次crontab的同学而言,可能遗忘配置语法会很快,这里我向大家推荐几个在线设置crontab任务的网站. ge ...
- 关于promise(一)
该新特性属于 ECMAScript 2015(ES6)规范,在使用时请注意浏览器兼容性. 由于ES6原生提供Promise,所以无需安装Promise库.但在ES5环境下我们可以使用bluebird库 ...
- 两款基于Jquery的图表插件
一.EasyPieChart 页面加载时,运行initPieChart()函数,调用easyPieChart()函数,显示出图表. 代码: var initPieChart = function() ...