Datagridview可为其每列设置排序属性SortMode,选项有NotSortable、Automatic、Programmatic,其中NotSortable为该列不可排序,Automatic为该列自动排序,Programmatic为程序员显性控制表格列排序(自定义一个比较器,用于行排序)。由于Programmatic需要程序员定义compare,因此通常情况下只指定SortMode为NotSortable或者Automatic即可。最近却在一个自定义开发的DatagridviewEX控件上(继承Datagridview)深受Automatic 排序之害。
DatagridviewEX继承Datagridview,主要有获取insertList, deleteList, updateList, 多列下拉编辑等功能,其中insertList, deleteList, updateList实现依赖于DatagridviewEX的一列不可见列rowstatus,通过设置其值{new, update, normal}来实现哪些行是新增,哪些行是更改行,删除行直接进入deleteList,关键是更改行如何识别。
更改行通过重写OnCellBeginEdit、OnCellEndEdit来实现。在OnCellBeginEdit事件中记录编辑单元格的原始值original,在OnCellEndEdit中判断其值是否与原始值一致,不一致的话,说明该行被编辑,然后置该行的rowstatus列值为update,在该列不可排序的情况下没问题,能准确的取出更改行记录数,但是在该列为可排序并且用户进行了排序的情况下,却出现了异常,更改行记录数老是取不对,后来经分析乃自动排序所致。
假设,当前更改的是第3条记录,那么其原始值为Rows[2].Cells[_更改列].Value,改完该单元格的值之后,由于该列的自动排序缘故,其排到了第一行,然而在OnCellEndEdit事件里,去改该行的rowstatus列值的时候,依旧修改的是第3行(此时实践上应该修改第一行的状态列才对),因此就导致状态列修改不对,去更改记录数不对的问题了。
由于自动排序的列,在编辑某单元格时,进入OnCellEndEdit时,已经重新排序,因此导致了rowstatus置错行、取更改记录数不准确现象。由于时间的关系,没去仔细分析Datagridview排序到底是何时被触发,何种情况下被触发,因此,目前暂时以下述方案解决自动排序引起的CellEndEdit事件处理问题。
1) 自动排序列不允许编辑;
2) 可编辑列一定要排序的话,开发人员务必使用Programmatic显性控制其排序。
注:Datagridview一般可根据其内在的datatable的rowstatus来获取哪些行是新增、哪些行是更改、哪些行是删除,如下:
Added 该行已添加到 DataRowCollection 中,AcceptChanges 尚未调用。
Deleted 该行已通过 DataRow 的 Delete 方法被删除。
Detached 该行已被创建,但不属于任何 DataRowCollection。DataRow 在以下情况下立即处于此状态:创建之后添加到集合中之前;或从集合中移除之后。
Modified 该行已被修改,AcceptChanges 尚未调用。
Unchanged 该行自上次调用 AcceptChanges 以来尚未更改。
但是,由于Datagridview和datatable的显示顺序不一致的问题,因此表格上看到的第一行未必是datatable的第一行,因此判断第一行是否更改过,就无法判断,为此未用datatable的rowstatus来取哪些行是新增,哪些行被更改过。