Winform DataGridView擴展系列(一)


寫一個win form的程序,要用到DataGridView的匯總行,網上找了找,不是要錢就是有點小問題。想了想,自己寫一個吧,看看以前打下的底子還中不,呵呵。

要寫就的有構想,前前后后想了幾天把我要的羅列了一下:匯總行、多列表頭(中國報表)、百分比列、計算器列、時間列、日期列。幾個DataGridVewColumn的繼承擴展沒啥難度,就前兩個要費點力。開工,干了。

先看看結果:

a)匯總行(繼承DataGridView控件實現)

b)多列表頭(組件方式的實現)

一、匯總行(繼承DataGridView控件)實現:

  1. 要求: 

    a.不影響DataGridView本身的運行,並盡量保持與DataGridView的整體外觀一致

    b.減少閃爍。

    c.提供較完整的設計時支持。

    2.實現:

    a.類層次結構

      

 1  ///   <summary>     
 2   
 3         ///  有底部分析區域的DataGridView控件類,繼承自DataGridView    
 4   
 5         ///   </summary>     
 6   
 7        public  class FootDataGridView : DataGridView{}
 8  
 9         ///   <summary>
10   
11         ///  Panel控件擴展類,應用於FootDataGridView    
12   
13         ///   </summary>     
14   
15        public  class FootBand : Panel
16  
17       {
18  
19          #region 附屬類
20  
21         [DefaultProperty( " ColumnName ")]        
22  
23          public  class FootItem{}
24  
25         [Editor( typeof(ZYQ.Design.Utilities.Editor.DataGridViewFootCollectionEditor), typeof(UITypeEditor))]        
26  
27          public  class FootItemCollection : List<FootItem>{}
28  
29          #endregion
30  
31       }

 

    b.設計時支持

     c.細節與實現:

      屬性和方法等的實現沒啥好說的,MSDN中都有。難度在呈現UI上。

      為減少閃爍,必須聲明開啟雙緩存。

       

private  void Initialize()        
 
      {            
 
         #region 聲明使用雙緩存            
 
        SetStyle(ControlStyles.DoubleBuffer |
 
                                     ControlStyles.OptimizedDoubleBuffer |
 
                                     ControlStyles.AllPaintingInWmPaint,
 
                                      true);
 
                UpdateStyles();
 
                 #endregion
 
        ......
 
      }

 

      為配合DataGridView的動作使匯總行跟隨改變,必須重寫一些事件引發的函數來重新計算匯總行繪制所需要的數據,他們是:

      

protected  override  void OnPaint(PaintEventArgs e),
 
       protected  override  void OnCellValueChanged(DataGridViewCellEventArgs e)
 
       protected  override  void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
 
       protected  override  void OnColumnDividerWidthChanged(DataGridViewColumnEventArgs e)
 
       protected  override  void OnGridColorChanged(EventArgs e)
 
       protected  override  void OnResize(EventArgs e)
 
       protected  override  void OnRowHeadersWidthChanged(EventArgs e)
 
       protected  override  void OnSizeChanged(EventArgs e)
 
       protected  override  void OnVisibleChanged(EventArgs e)
 
       protected  override  void OnScroll(ScrollEventArgs e)
 
       protected  override  void OnColumnRemoved(DataGridViewColumnEventArgs e)
 
       protected  override  void OnBackgroundColorChanged(EventArgs e)
 
       protected  override  void OnRowHeadersDefaultCellStyleChanged(EventArgs e)
 
       protected  override  void OnColumnStateChanged(DataGridViewColumnStateChangedEventArgs e)

 

      匯總行的繪制必須是在DataGridView創建后才開始的,所以必須獲得DataGridView的HandleCreated事件的通知;而要繪制匯總行必須使用Panel的Paint事件.

      

  private  void Initialize()        
 
      {
 
        ......
 
         base.HandleCreated +=  new EventHandler(FootDataGridView_HandleCreated);
 
        _foot.Paint +=  new PaintEventHandler(_foot_Paint);
 
        ......
 
      }
 
       void FootDataGridView_HandleCreated( object sender, EventArgs e)
 
            {            
 
        _foot.ParentIsCreated =  this.Created;
 
           }
 
       void _foot_Paint( object sender, PaintEventArgs e)
 
             {                           
 
        // 畫分割線
 
              if (ShowDividedLine)
 
             {
 
           OnPaintDividedLine(e.Graphics);
 
              }
 
               // 畫foot header
 
               if (RowHeadersVisible)
 
                {
 
                OnPaintFootHeader(e.Graphics);
 
                }
 
                   // 畫底部區域
 
                  OnPaintColumnsFoot(e);
 
      }

 

      所有重寫的事件引發函數調用RaisePanel()函數來引發Panel的Paint事件

      

             private  void RaisePanel()
 
            {
 
         if (_foot.Visible)
 
                {
 
                      if (Created)
 
                     {
 
                           ResetButtomPanel();
 
                           PaintEventArgs parg =  new PaintEventArgs(_foot.CreateGraphics(), _foot.ClientRectangle);
 
                           ClearFoot(parg.Graphics);
 
                           _foot_Paint(_foot, parg);
 
                     }
 
                }
 
           }

 

     繪制過程用GDI+,沒什么特別的,只要搞清楚剪輯使用的就行了。

使用下來感覺很好,和DataGridView配合很好,沒有閃爍的情況。后續開發的時候可以利用Panel的特性加入鼠標、綁定、重算等功能。

 

轉載請注明:http://www.cnblogs.com/RZYQ/archive/2011/12/28/2305257.html

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM