现windows应用程序中用的datagrid具有分页功能

80酷酷网    80kuku.com

  datagrid|window|程序|分页

工作需要,要实现windows应用程序中用的datagrid具有分页功能,不知道ms怎么想的,asp.net的datagrid有这样的功能,为什么不在winForm的datagrid里面提供这样的功能,还得让我费这么大劲儿来重写这个控件,真是麻烦。

首先,我们要做一个类来继承系统的datagrid:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

 

namespace oilx.PagingDataGrid

{

public class PagingDataGrid : DataGrid

{

  // 声明一些必要的全局变量。

private System.ComponentModel.Container components = null;

 

                      /// <summary>

                      ///                  

/// </summary>

                      private const int MarkerWith = 14;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private Point      _pointTopLeft; 

 

                      /// <summary>

                      ///

                      /// </summary>

                      private int _row = 1;

 

                      //

                      private int _rowNumberFigure = 0;

                      private bool _zeroPadding = false;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private string _rowHeaderCaption = String.Empty;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private int _pageSize = 10;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private int _currentPageCount = 1;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private bool _allowPaging = false;

 

                      /// <summary>

                      ///

                      /// </summary>

                      private int _previousPageCount = -1;

                      /// <summary>

                      ///

                      /// </summary>

                      private DataTable _pageDataSource;

 

/// <summary>

///构造函数

/// </summary>

/// <param name="container"></param>

public PagingDataGrid (System.ComponentModel.IContainer container)

{

           container.Add(this);

           InitializeComponent();

           InitiarizeControl();

}

/// <summary>

///构造函数重载

/// </summary>

public FixdItemDataGrid()

{

           InitializeComponent();

           InitiarizeControl();

                                 

}

// 下面我们需要增加一些用于分页的公共属性

/// <summary>

/// 页面大小,即每页现实的数据条数

/// </summary>

[Browsable(true),Description("页面大小")]

public int PageSize

{

           get

           {

                      return _pageSize;

           }

           set

           {

                      _pageSize = value;

           }

}

/// <summary>

/// 分页数

/// </summary>

[Browsable(true),Description("分页数")]

public int PageCount

{

           get

           {

                      if(DataSource == null)

                      {

                                  return 0;

                      }

                      if(_pageDataSource == null || _pageDataSource.Rows.Count <= 0)

                      {

                                  return 0;

                      }

                      int i = _pageDataSource.Rows.Count%PageSize==0?0:1;

                      return _pageDataSource.Rows.Count/PageSize+i;

           }

}

/// <summary>

/// 当前页数

/// </summary>

[Browsable(true),Description("当前页数")]

public int CurrentPageCount

{

           get

           {

                      if(_currentPageCount < 0)

                      {

                                  return 1;

                      }

                      if(_currentPageCount >= PageCount)

                      {

                                  return PageCount;

                      }

                      return _currentPageCount;

           }

           set

           {

                      if(value >=PageCount)

                      {

                                  _currentPageCount =  PageCount;

                      }

                      _currentPageCount = value;

           }

}

/// <summary>

///是否允许分页

/// </summary>

[Browsable(true),Description("是否允许分页")]

public bool AllowPaging

{

           get

           {

                      return _allowPaging;

           }

           set

           {

                      _allowPaging = value;

           }

}

/// <summary>

///行标题

/// </summary>

[Browsable(true),Description("行标题")]

public string RowHeaderCaption

{

           get

           {

                      return _rowHeaderCaption;

           }

           set

           {

                      _rowHeaderCaption = value;

           }

}

 

// 基本工作都作完了,下面开始我们分页的重点,go!

// 我们需要重写系统一个方法,那就是:

/// <summary>

/// 该方法在数据源被修改的时候激活。

/// </summary>

/// <param name="e"></param>

protected override void OnDataSourceChanged(System.EventArgs e)

{

           base.OnDataSourceChanged(e);

           // 如果数据源为空那么就返回。

           if( this.DataSource == null )

           {

                      return;

           }

           // 下面判断数据源的类型,一般情况下,datagrid数据源形式为3种,1,dataset,2,datatable,3,dataview。

           // 在这里我们要做的是把数据源的数据保存到另外一个变量里面,这样当我们在作分页

           //的时候,需要修改数据源时,可以把这个变量当作原始的数据源来进行判断。

           if(this.DataSource is DataSet)

           {

                      if( ((DataSet)DataSource).Tables.Count > 0)

                      {

                                  this.DataSource = ((DataSet)DataSource).Tables[0];

                      }

                      else

                      {

                                  return;

                      }

           }

           if(_pageDataSource == null)

           {

                      if(DataSource is DataSet)

                      {

                                                        if(((DataSet)DataSource).Tables[0].Rows.Count <=0)

           {

                      return;

           }

           _pageDataSource = ((DataSet)DataSource).Tables[0].Clone();

           for(int i = 0;i<((DataSet)DataSource).Tables[0].Rows.Count;i++)

           {

                      DataRow drRow = _pageDataSource.NewRow();

                      drRow.ItemArray = ((DataSet)DataSource).Tables[0].Rows[i].ItemArray;

                      _pageDataSource.Rows.Add(drRow);

           }

}

           else if(DataSource is DataTable)

           {

                      if(((DataTable)DataSource).Rows.Count <= 0)

                      {

                                  return;

                      }

                      _pageDataSource = ((DataTable)DataSource).Clone();

           for(int i = 0;i<((DataTable)DataSource).Rows.Count;i++)

           {

                      DataRow drRow = _pageDataSource.NewRow();

                      drRow.ItemArray = ((DataTable)DataSource).Rows[i].ItemArray;

                      _pageDataSource.Rows.Add(drRow);

           }

}

else if(DataSource is DataView)

{                    

if( ((DataView)DataSource).Table.Rows.Count <= 0)

           {

                      return;

           }

           _pageDataSource = ((DataView)DataSource).Table.Clone();

           for(int i = 0;i<((DataView)DataSource).Table.Rows.Count;i++)

           {

                      DataRow drRow = _pageDataSource.NewRow();

                      drRow.ItemArray = ((DataView)DataSource).Table.Rows[i].ItemArray;

                      _pageDataSource.Rows.Add(drRow);

           }

}

}

_pointTopLeft = new Point(this.GetCellBounds(0,0).X + 4, this.GetCellBounds(0,0).Y + 4);

}

// 上面的所作的只是把原数据源数据导入到_pageDataSource这个datatable里面,在这里有

//人可能要问为什么不用 _pageDataSource = (DataTable)this.DataSource;

// 而使用

//DataRow drRow = _pageDataSource.NewRow();

//drRow.ItemArray = ((DataView)DataSource).Table.Rows[i].ItemArray;

//_pageDataSource.Rows.Add(drRow);

//这是因为DataTable是引用类型,如果直接付值的话,那么当原数据源的数据被修改时,——//_pageDataSource也会被修改。

//好了,临时数据已经处理完了,那么真正的分页处理开始,大家都知道,.net控件要显示在窗体//上,那么需要我们把它的实体画上去,那么ms.net在所有控件都提供了下面这样的方法,可以//让我们把控件按照我们修改后的形式表现出来:

/// <summary>

///

/// </summary>

/// <param name="e"></param>

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

{

base.OnPaint(e);

           if( this.DataSource == null )

           {

                      return;

           }

           if(DataSource != null && DataSource is DataSet)

           {

                      return;

           }

           // 在这里我们开始对分页进行进行处理          

           if(AllowPaging)

           {

                      if(_pageDataSource != null)

                      {

                                  if(_previousPageCount != CurrentPageCount)

                                  {

                                             // 判断当前是第几页

                                             int i = CurrentPageCount*PageSize-PageSize;

                                             if(i<0)

                                             {

                                                        i = 0;

                                             }

//下面判断是否为最后一页

                                             if(i <= _pageDataSource.Rows.Count)

                                             {

                                                        DataTable dtPage = _pageDataSource.Clone();

                                                        int iCount = 0;

           根据PageSize来生成一个dataTable,重新进行数据源绑定。

           for(;i<_pageDataSource.Rows.Count;i++)

           {

                                                                             

                      DataRow drRow = dtPage.NewRow();

                                                                                          drRow.ItemArray= _pageDataSource.Rows[i].ItemArray;

                                                                                          dtPage.Rows.Add(drRow);

                      iCount ++;

                                                                                          if(iCount>=PageSize)

           {

                      break;

           }

           }

           // 绑定新的数据源

           this.DataSource = dtPage;

}

_previousPageCount = CurrentPageCount;

}

}

}

           // RowHeaders如果为true,那么我们要给RowHeader上面标上序号和标题

           if(this.RowHeadersVisible)

           {

                      DataGrid.HitTestInfo hti = this.HitTest(_pointTopLeft);

                      int iRowhti = hti.Row;

                      if(iRowhti < 0)

                      {

                                  iRowhti = 0;

                      }

                      int iDelta = this.GetCellBounds(iRowhti, 0).Height + 1;

                      int iHeight = this.GetCellBounds(iRowhti, 0).Top + 1;

                      // 这个方法里面是显示RowHeaders的标题,详见该方法实现

                      ShowColumnTitles(e);

                      CurrencyManager cm = (CurrencyManager) this.BindingContext[this.DataSource, this.DataMember];

                      while(iHeight < this.Height - iDelta && iRowhti < cm.Count)

                      {

                                  string strText = String.Empty;

                                  if(_zeroPadding)

                                  {

                                             strText = String.Format("{0}", _row + iRowhti).PadLeft(_rowNumberFigure, '0');

                                  }

                                  else

                                  {

                                             strText = String.Format("{0}", _row + iRowhti);

                                  }

                                  e.Graphics.DrawString(strText, this.Font, new SolidBrush(Color.Black), 20, iHeight);

                                  // 下面处理的是在RowHeaders上面画一条分割线,为了有阴影的感觉,我画了一条灰色和白色两条,看着还挺像 ^_^

                                  if(!this.CaptionVisible)

                                  {

                                            ShowSepalatorLine(e, new Point(17, 2), new Point(17, iHeight-2 + this.PreferredRowHeight),Color.Gray);

                                             ShowSepalatorLine(e, new Point(18, 2), new Point(18, iHeight-2 + this.PreferredRowHeight),Color.White);

                                  }

                                  else

                                  {

                                             ShowSepalatorLine(e, new Point(17, 20), new Point(17, iHeight-2 + this.PreferredRowHeight),Color.Gray);

                                            ShowSepalatorLine(e, new Point(18, 20), new Point(18, iHeight-2 + this.PreferredRowHeight),Color.White);

                                  }

                                  iHeight += iDelta;

                                  iRowhti++;

                      }

                      _row =CurrentPageCount*PageSize-PageSize+1;

                      if(_row < 0)

                      {

                                  _row =1;

                      }

           }

}

// 画线

private void ShowSepalatorLine(PaintEventArgs e, Point ptStart, Point ptEnd,Color lineColor)

{

           Pen pen = new Pen(new SolidBrush(lineColor), 1);

           e.Graphics.DrawLine(pen, ptStart, ptEnd);

}

/// <summary>

/// 显示RowHeaders的标题

/// </summary>

/// <param name="e"></param>

/// <param name="source"></param>

private void ShowColumnTitles(PaintEventArgs e)

{

           string strHeader = RowHeaderCaption;

           int iX     = MarkerWith + 5;

           int iWith  = this.RowHeaderWidth;

           using(StringFormat sf = new StringFormat())

           {

                      sf.FormatFlags   = StringFormatFlags.NoWrap;

                      sf.Trimming      = StringTrimming.EllipsisCharacter;

                      sf.Alignment     = StringAlignment.Near;

                      sf.LineAlignment = StringAlignment.Center;

                      RectangleF rect;

                      if(!CaptionVisible)

                      {

                                  rect = new RectangleF(new PointF(iX, 3), new SizeF(iWith, this.PreferredRowHeight));

                      }

                      else

                      {

                                  rect = new RectangleF(new PointF(iX, 20), new SizeF(iWith, this.PreferredRowHeight));

                      }

                      e.Graphics.DrawString(strHeader, this.Font, new SolidBrush(Color.Black), rect, sf);

           }

}

/// <summary>

/// ?}?E?X?|?C?“?^‚???“®¸?—¯

/// </summary>

/// <param name="e"></param>

protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)

{

           DataGrid.HitTestInfo hitTestInfo = this.HitTest(new Point(e.X, e.Y))          if(hitTestInfo.Type == DataGrid.HitTestType.RowResize)

           {

                      return;

           }

           base.OnMouseMove(e);

                      }

 

/// <summary> ///

/// </summary>

/// <param name="e"></param>

protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)

{

           DataGrid.HitTestInfo hitTestInfo = this.HitTest(new Point(e.X, e.Y));

           if(hitTestInfo.Type == DataGrid.HitTestType.RowResize)

           {

                      return;

           }

           base.OnMouseDown(e);

}         

}

} 好了,到这里这个,这个分页的datagrid就算完了。程序实现:dataGrid1.CurrentPageCount ++;dataGrid1.Invalidate();一定要写dataGrid1.Invalidate();这个方法,不然datagrid不能刷新,看不到分页效果!

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: