工作需要,要实现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); 
}          
} 
} 在使用Infragistics.Win.UltraWinGrid.UltraGrid时,有时我们想在网格上进行双击操作。比如双击某一行来显示对应的明细数据。但是对于双击事件来说并没有提供对应的行信息。那么我们如何来判断用户双击某一行呢。这里我还是以代码来说明,相信大家都能明白
private void ultraGrid1_DoubleClick(object sender, System.EventArgs e)
   {
    //双击测试,察看当前双击地方是不是一行,如果是则弹出窗体//获取当前双击点的位置
    Point p=System.Windows.Forms.Cursor.Position; //获取当前双击点在网格中所处的位置
    p=this.ultraGrid1.PointToClient(p);//获取双击点网格控件的元素
    Infragistics.Win.UIElement oUI=this.ultraGrid1.DisplayLayout.UIElement.ElementFromPoint(p);
    if(oUI!=null)
    {//判断双击点是不是行,也可能是列,如果网格控件选取方式不是设的选中整行的话。
     Infragistics.Win.UltraWinGrid.UltraGridRow oRowUI = oUI.SelectableItem as Infragistics.Win.UltraWinGrid.UltraGridRow;    if(oRowUI !=null)
     {
         //如果选中的是行,则我们可以通行行的单元格来获取对应的信息     string s=oRowUI .Cells[0].Value.ToString();
    }
    
    }
    
     
    
   }

好了,到这里这个,这个分页的datagrid就算完了。

程序实现:

dataGrid1.CurrentPageCount ++;

dataGrid1.Invalidate();

一定要写dataGrid1.Invalidate();这个方法,不然datagrid不能刷新,看不到分页效果!