表达式列的特殊性

我们知道,列的值发生变化,会相继触发DataColChanging和DataColChanged事件。
但是有一个例外: 表达式列的值发生变化时,并不会触发这两个事件。

假定C列是一个表达式列,根据A列和B列的值计算得出,而D列的值则根据C列的值用代码计算得出。
通常我们会这样编写DataColChanged事件的代码:

Select Case e.DataCol.Name
   
Case "C"
         
'计算D列的代码
End Select

但是上述代码是无效的,因为作为表达式列,C列发生变化的时候,并不会触发DataColChanged事件。

我们可以换个思路,既然C列是有A列和B列计算得出,那么C列发生变化,肯定是因为A列或B列发生变化引起的。
所以正确的代码是:

Select Case e.DataCol.Name
    Case "A" ,"B"
         
'计算D列的代码
End
Select

通过子表触发父表事件

还有一个特殊情况,表达式列并非由本表的列计算得出,而是由子表数据计算得出。
例如假定订单表有个数量列,是表达式列,用于累计订单明细表的数量,其表达式为:
Sum(Child.数量)。
再假定订单表的DataColChanged事件设置了如下代码:

If e.DataCol.name = "数量" Then
  '相关计算代码 
End If

当我们在订单明细表输入数量时,订单表的数量会自动更新,但是上面的代码永远不会执行,因为数量是一个表达式列,不会触发事件。
我们需要在订单明细表的
DataColChanged事件加上代码:

If e.DataCol.name = "数量" Then
    Dim
pr As DataRow = e.DataRow.GetParentRow("订单") '找出对应的父行
    If
pr IsNot Nothing Then
        DataTables(
"订单").DataCols("数量").RaiseDataColChanged(pr '通知系统此父行的数量列发生了改变,触发DataColChanged事件
    End If
End If

这样在订单明细表输入数量,就会在订单表针对该订单的数量列触发DataColChanged事件。

有的用户编写代码不严谨,简单地将订单明细的代码设置为:

If e.DataCol.name = "数量" Then
    DataTables(
"订单").DataCols("数量").RaiseDataColChanged
End If

上面的代码效率极低,因为修改某个订单明细的数量,就会重算所有订单的数量,而不是只重算相应订单的数量。


本页地址:http://www.foxtable.com/webhelp/topics/2381.htm