关与 DataGridView 加合计行,最新突破
基本情况描述:
在DataGridView最下端加一行合计行,而且这一行是冻结不动行。
探索过程:
1)有人建议用datatable的Rows.Add+Compute来合计,但是无法实现一直在底部可见,而且输入数据的时候也很难处理,是最傻的方法。
2)有人建议用在datagridview CellPainting /RowPostPainting事件往datagridview 底部画线,画值,可是有个严重的问题是,当拖动滚动条的时候会被遮盖住了,也是一种没把最根本问题解决的思路。
3)定义一个自定义控件DataGridViewFooter,能根据DataGridView的列和值自动画表格和统计值,在 DataGridView OnPaint方法里把Footer 画出来,这是一种把根本问题解决的思路,可是难度很大。
4)做用户控件(UserControl),用两个DataGridView来显示,配合VScrollBar来显示滚动,现在本人暂时用这个方法先处理,可是在加载Column的时候很不方便,要自己写代码,浪费时间。
现在重点考虑方法3,通过Reflector窥看修改datagridview难点:
控件首先会触发OnLayout事件,把datagridview里的VScrollBar、HScrollBar、RowsHeader、ColumnHeader、Data这几个区域的位置和大小都算好,主要计算方法是PerformLayoutPrivate里的ComputeLayout,储存这些数据的是DataGridView私有变量layout。
好,明白这里后,本人在OnLayout事件之后,利用.net的反射机制,把加上DataGridViewFooter后的布局数值设置到layout去具体代码如下:
if (base.IsHandleCreated)
{
Type t = this.GetType();
FieldInfo fieldInfoLayout = t.BaseType.GetField("layout", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfoLayout == null) return;
Object layoutData = fieldInfoLayout.GetValue(this);
if (layoutData == null) return;
//reset layout's data and rowheader field rectangle
Type typeLayoutData = layoutData.GetType();
FieldInfo fieldInfoData = typeLayoutData.GetField("Data");
FieldInfo fieldInfoRowHeaders = typeLayoutData.GetField("RowHeaders");
MethodInfo methodInfoComputeVisibleRows = t.BaseType.GetMethod("ComputeVisibleRows", BindingFlags.NonPublic | BindingFlags.Instance);
this._dataclient = (Rectangle)fieldInfoData.GetValue(layoutData);
this._dataclient = new Rectangle(this._dataclient.X, this._dataclient.Y, this._dataclient.Width, this._dataclient.Height-this._datagridviewfooter.Height);
Rectangle rectRowHeader = (Rectangle)fieldInfoRowHeaders.GetValue(layoutData);
rectRowHeader = new Rectangle(rectRowHeader.X, rectRowHeader.Y, rectRowHeader.Width, rectRowHeader.Height - this._datagridviewfooter.Height);
fieldInfoData.SetValue(layoutData, this._dataclient);
fieldInfoRowHeaders.SetValue(layoutData, rectRowHeader);
methodInfoComputeVisibleRows.Invoke(this, null);
fieldInfoLayout.SetValue(this, layoutData);
}
改好了,在滚动的过程中,VScroll是没有问题的,可是在HScroll就出问题了,估计是系统会触发OnColumnStateChanged了事件调用了PerformlayoutPrivate方法把布局又重新算了一遍。
而且改了layout后,还有个问题是在edit的时候,在算FirstDisplayRowIndex的时候会出错。
这两个问题都不得而解,所以发贴让大家再讨论一下。
------解决方案--------------------人家给你建议吧,你说是最傻的办法。
------解决方案--------------------顶,不错,有研究精神,CPIO实现的效果也不错.
祝楼主早日攻课难关!
------解决方案--------------------今天与未来顶一下
------解决方案--------------------很好 很强大