你的位置:首页 > 软件开发 > ASP.net > 【C#】让DataGridView输入实时更新数据源中的计算列

【C#】让DataGridView输入实时更新数据源中的计算列

发布时间:2015-05-29 00:00:52
本文适用Winform开发,且DataGridView的数据源为DataTable/DataView的情况。理解前提:熟知DataTable、DataView求:更好方案考虑这样一个场景:某DataTable(下称dt)的B列是计算列(设置了Expression属性),是根据A列 ...

本文适用Winform开发,且Dataget='_blank'>GridView的数据源为DataTable/DataView的情况。

理解前提:熟知DataTable、DataView

求:更好方案

考虑这样一个场景:

某DataTable(下称dt)的B列是计算列(设置了Expression属性),是根据A列的数据计算而来,该dt被绑定到某个DataGridView(下称dgv),A、B两列都要在dgv中显示,其中A列可编辑(ReadOnly=false)。需求是对A列进行编辑时(输入或删除),B列能实时变化。例如下面的例子:

【C#】让DataGridView输入实时更新数据源中的计算列

【目标文件名】是根据【款号】和【色号】计算而来(连接字符串),当编辑款号/色号时,目标文件名能实时变化。

熟悉dgv的猿友都知道,如果不做特别处理,是达不到上述效果的。原因是dgv默认是等焦点离开编辑单元格(CurrentCell),才会提交更改到数据源,而且就算焦点离开,但如果焦点仍在同一行(即CurrentCell改变,但CurrentRow没变)的话,该行的源行也仍然处在编辑状态(DataRowView.IsEdit为true),计算列也同样不会更新。非得是焦点离开这一行(去到别的行,或者其它控件),计算列才会更新。——这段话信息量略大,不熟悉dgv提交机制的猿友可能得借助下面进一步的说明才能明白~老鸟请绕道。先认识几个概念:

  • dgv单元格:DataGridViewCell
  • dgv行:DataGridViewRow
  • dgv行的源行:DataRowView。当dgv绑定数据源后,它的每一行就对应了数据源中的一行(或叫一项),这就是我所谓的【源行】。可以通过DataGridViewRow.DataBoundItem属性获得,该属性类型是object,当dgv的数据源为DataTable或DataView(下称dv)时,DataBoundItem的真实类型就是DataRowView,可以理解为DataView的行。而dv又是根据dt来的,所以dv背后又对应一个dt,所以DataRowView背后也对应一个DataRow,可通过DataRowView.Row获得该DataRow。简单表示就是,DataGridViewRow(访问DataBoundItem属性)→DataRowView(访问Row属性)→DataRow
  • dgv有单元格的概念和实体类(DataGridViewCell),但dt和dv没有,后者只到行这一级,虽然可以通过DataRow[x]或DataRowView[x]访问单元格的值,但在类层级上并不存在DataCell这样的表示单元格的实体类,也就是dt和dv的编辑/提交等操作是以【行】为单元

下面是dgv的常规提交流程:

①编辑dgv单元格→②完成编辑(离开焦点)→③提交数据源(源行仍处于编辑状态)→④焦点离开dgv行→⑤源行结束编辑状态→⑥源行更新计算列(其实完整流程还包括别的环节,比如单元格数据验证,但这里只说与提交直接相关的环节)。

可以看到,计算列得到更新的关键有两处:

  1. dgv单元格的数据要提交到数据源相应单元格
  2. 源行结束编辑状态

按常规提交流程,必须使焦点离开单元格所在的行(只离开单元格都不行哦)才能达到目的,而我们的需求是,编辑的过程中就要实时更新,不要说离开行,连单元格都不想离开。

一、解决实时更新计算列的问题

可以通过dgv的CurrentCellDirtyStateChanged事件达到目的:

private void dgv_CurrentCellDirtyStateChanged(object sender, EventArgs e){  //判断当前单元格是否存在未提交的更改,只有存在才继续。  //此判断有必要,因为下面的dgv.CommitEdit也会触发该事件,但此时IsCurrentCellDirty已为false,  //如果不做判断,将会重复进入,造成无谓消耗  if (dgv.IsCurrentCellDirty)  {    //将单元格值提交给数据源,dgv.EndEdit()也能做到提交,但那样会使单元格结束编辑状态    //而dgv.CommitEdit()则会保持编辑状态    //参数是提供给DataError等事件的原因    dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);        //人工结束源行的编辑状态。只有这样,源行的计算列才会更新    (dgv.CurrentRow.DataBoundItem as DataRowView).EndEdit();        //或者执行DataRow的EndEdit()也能达到同样目的    //(dgv.CurrentRow.DataBoundItem as DataRowView).Row.EndEdit();  }}

原标题:【C#】让DataGridView输入实时更新数据源中的计算列

关键词:C#

C#
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录