在6.2更新中,RaiseDataColChanged有了一个新的语法:
RaiseDataColChanged(Filter)
Filter: 可选参数,一个条件表达式,针对符合此条件的行触发
增加这个语法,是为了更方便地实现跨表计算的自动更新。
夸表更新
上一节提到,通过在订单表的DataColChanged事件中加入如下代码:
If e.DataCol.Name = "产品名称" Then '如果内容发生变动的是产品列
If e.NewValue Is Nothing Then '如果新值是空白,也就是产品列的内容为空
e.DataRow("单价") = Nothing '那么清空此行单价列的内容
Else
Dim dr As DataRow
'否则在产品表查找同名的产品行,将找到的行赋值给变量dr
dr = DataTables("产品").Find("[产品名称] = '" & e.NewValue & "'")
If dr IsNot Nothing Then '如果找到了同名的产品行,也就是dr不是Nothing
e.DataRow("单价") = dr("单价")
End If
End If
End If
可以使得订单表自动从产品表中取得对应产品的单价,然后填入订单表的单价列。
如果我们修改某一个产品的单价,那么该产品原有订单的单价会保持不变,只有新增的订单才会使用新的单价。
可是也有一些场合,可能会要求修改产品单价后,原有订单的产品单价也自动更新。
为此,我们可以在产品表的DataColChanged事件中加入如下代码:
If e.DataCol.Name = "单价"
Dim Filter As String = "[品名] = '" & e.DataRow("品名") & "'"
DataTables("订单").DataCols("品名").RaiseDataColChanged(Filter)
End If
上述代码的原理是:如果修改了产品表的单价,则针对订单表的品名列触发DataColChange事件,触发条件为订购此产品的行,从而实现了订单表单价的自动更新。
RaiseDataColChanged的条件是动态合成的,条件表达式分为三部分
"[品名] = '" & e.DataRow("品名") & "'"
如果品名为"PD01",那么三部分组合起来的结果是:
[品名] = 'PD01'
这是我们第二次介绍动态合成表达式,这是属于基本功,不掌握是不行的。
有条件的跨表更新
上面我们已经介绍了如何实现跨表更新,可是更新有的时候是有条件的。
例如如果在产品表中修改单价,希望订单表中已经锁定的订单,继续保持原单价不变,而未锁定的订单采用新的单价。
为此,我们可以在产品表的DataColChanged事件中加入如下代码:
If e.DataCol.Name = "单价"
Dim Filter As String = "[品名] = '" & e.DataRow("品名") & "'"
Dim drs As List(Of DataRow) = DataTables("订单").Select(Filter)
For Each dr As DataRow In drs
If dr.Locked = False '如果此行没有锁定
DataTables("订单").DataCols("品名").RaiseDataColChanged(dr)
End If
Next
End If
一定要用RaiseDataColChanged吗?
当然不,例如我们可以用下面的代码,同样可以实现上面的要求:
If e.DataCol.Name = "单价"
Dim Filter As String = "[品名] = '" & e.DataRow("品名") & "'"
Dim drs As List(Of DataRow) = DataTables("订单").Select(Filter)
For Each dr As DataRow In drs
If dr.Locked = False '如果此行没有锁定
dr("单价") = e.DataRow("单价") '则采用新的单价
End If
Next
End If
看上去代码似乎更简单一些。不过大多数时候,还是用RaiseDataColChanged方法较好,因为:
1、如果使用RaiseDataColChanged实现自动更新,更新代码不会涉及具体的计算,所以代码是通用的,基本上不会因为计算要求的变动,而去修改更新代码。
2、如果不使用RaiseDataColChanged实现自动更新,那么更新代码必须包含计算功能,等于基本类似的代码同时出现在两个位置;代码简单的话(例如本节的例子)倒无所谓,如果计算部分的代码较为复杂,就显得累赘了,也不便于维护。