木木的大象

导航

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

  

posted on 2011-12-28 00:19  木木的大象  阅读(7738)  评论(0编辑  收藏  举报