在网络上看过很多关于DataGridView合计的设计及源码,搜到了很多相同的文章(都是相互复制),效果不如人意, 很多的人写的解决办法如下几条:
- 把DataGridView的最后一行作为合计行,每增加或删除一行后重新计算合计行。
- 用两个大小相同的DataGridView,一个是数据表格,一个是合计表格。
- 第三个是用Table类SUM增加一条合计行数据,再显示到DataGridView中。
- 干脆用第三方控件。。。。。。。。
以上出现的问题:
合计行不能显示在DataGridView界面的最下方,用户只能滚条到表格最后才能看到合计。
如果用两个DataGridView,我想性能怎么样,大家可想而知。
如果用Table类SUM一条,同样会产生只能要最后一行看到,如果别人不使用Table显示到DataGridView中怎么办。
上述的都不能很好的解决DataGridView合计行,以下是我个人设计原理与说明:
首先我们解决的是不管用什么方式填充DataGridView数据都能够合计数据。
必须显示在DataGridView界面的最下方,这样用户体验深刻一点。
从上我们可以看到,我们要做到合计行的话,我们必须在表现层(UI)做,不要在逻辑层与数据层做,(如果出错的话只是显示错误)
最终效果如下:
合计我使用的是Lable对象。DataGridView需要处理的事件有单元格的数据改变事件CellValueChanged,滚动条事件,列宽事件,这件事件发生后重绘Lable及计算所需要列数据。
定义对象:Lable对象名为FootSumLabel,DataGridView对象名为DetailDataGrid
//定义类的私有变量,两个是滚动条
HScrollBar hs;
VScrollBar vs;
//合计数值
decimal fSumQty = 0, fSumCBAmount = 0;
//加载数据时先注册DetailDataGrid的滚动条事件,在类的构造时注册//DetailDataGrid类中包括有HScrollBar,VScrollBar如下
//hs_ValueChanged,vs_ValueChanged两个事件都重绘FootSumLabel,即FootSumLabel.Invalidate();这一句语句
hs = ((HScrollBar)this.DetailDataGrid.Controls[0]);
vs = ((VScrollBar)this.DetailDataGrid.Controls[1]);
hs.ValueChanged += new EventHandler(hs_ValueChanged);
vs.ValueChanged += new EventHandler(vs_ValueChanged);
//DetailDataGrid的CellValueChanged事件调用sumdata();
//FootSumLabel的重绘Paint事件
private void FootSumLabel_Paint(object sender, PaintEventArgs e)
{
int count = DetailDataGrid.Columns.Count;
DataGridViewColumnCollection Columns = this.DetailDataGrid.Columns;
Graphics grf = e.Graphics;
int x = this.DetailDataGrid.RowHeadersWidth - 2;
StringFormat strfmt = new StringFormat();
strfmt.Alignment = StringAlignment.Far;
for (int i = 0; i < count; i++)
{
x += Columns[i].Width;
if (i == 4)
{
int xx = x + Columns[i + 1].Width;
grf.DrawString(string.Format("{0:F2}", fSumQty), this.FootSumLabel.Font, Brushes.Black, xx - hs.Value, 3, strfmt);
}
if (i == 7)
{
int xx = x + Columns[i + 1].Width;
grf.DrawString(string.Format("{0:F2}", fSumCBAmount), this.FootSumLabel.Font, Brushes.Black, xx - hs.Value, 3, strfmt);
}
}
}
//合计数值函数
private void sumdata()
{
fSumQty = 0;
fSumCBAmount = 0;
DataGridViewRowCollection rows = this.DetailDataGrid.Rows;
foreach (DataGridViewRow row in rows)
{
fSumQty += Convert.ToDecimal(row.Cells["fQty"].Value);
fSumCBAmount += Convert.ToDecimal(row.Cells["fAmount"].Value);
}
//重画
this.FootSumLabel.Invalidate();
}
以上代码可以自行加工成一个类,DataGridView调整列宽的事件只要调用重绘FootSumLabel就可以了。如果有不正之处请指出。
如果要转帖请注明出处:http://www.cnblogs.com/NetWZ/articles/1862097.html 作者:.NetWZ