寫一個win form的程序,要用到DataGridView的匯總行,網上找了找,不是要錢就是有點小問題。想了想,自己寫一個吧,看看以前打下的底子還中不,呵呵。
要寫就的有構想,前前后后想了幾天把我要的羅列了一下:匯總行、多列表頭(中國報表)、百分比列、計算器列、時間列、日期列。幾個DataGridVewColumn的繼承擴展沒啥難度,就前兩個要費點力。開工,干了。
先看看結果:
a)匯總行(繼承DataGridView控件實現)
b)多列表頭(組件方式的實現)
一、匯總行(繼承DataGridView控件)實現:
- 要求:
a.不影響DataGridView本身的運行,並盡量保持與DataGridView的整體外觀一致
b.減少閃爍。
c.提供較完整的設計時支持。
2.實現:
a.類層次結構
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上。
為減少閃爍,必須聲明開啟雙緩存。
{
#region 聲明使用雙緩存
SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint,
true);
UpdateStyles();
#endregion
......
}
為配合DataGridView的動作使匯總行跟隨改變,必須重寫一些事件引發的函數來重新計算匯總行繪制所需要的數據,他們是:
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事件.
{
......
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事件
{
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