过去(面对对象编程出现以前的时候)许多人都知道SCATTER 和 GATHER MEMVAR命令的使用。VFP现在给了我们通过对象来做同样的事情的方法,而且更加简单。
现在假设你有一张客户表(Customer)只包括“名字”和“姓”两个字符型字段,你不妨建立一张表试一下
随便建立一张自由表,包括两个字段“名字”字符型(30)、“姓”字符型(30)。
浏览这张表并随便输入几个记录。在浏览的时候按下ctrl+Y键来增加一个新记录并输入随便什么人的姓名。
现在新建一个表单,给表单添加一个自定义属性'thisrec'。
向数据环境中添加入你的客户表(Customer)。
在表单的load方法中,选择客户表(Customer),并用scatter命令分散空白记录到对象。
Select customer && 也许表已经被选中了,但为了安全起见还是再选择一下
scatter name thisform.thisrec blank
scatter命令的用法:
scatter命令:用来从一个表中的当前记录从拷贝数据到一系列的变量或一个数组中。
scatter MemVar:会自动建立与字段名相同的一系列变量。
scatter to arrayName:建立一个数组,将每个字段的数据放到数组的元素中。
scatter Name objectName:会建立一个对象,对象的每个属性名与字段名相同,值为字段的数据。
scatter:命令后加上blank参数则建立的变量、数组或对象的属性值为空。
一般来说,scatter命令与Gather命令合用,scatter命令收集数据,对数据进行修改后用Gather命令保存到表中的当前记录。
同时,在这里要注意的是:thisrec本是表单的一个属性,但使用了scatter语句后,就把这个属性当成一个对象用了!!!我不知道这算是个什么对象,从调试器的局部窗口里也看不到它的父类是什么,只有“对象”两个字而已,这个对象也只有以字段名为名称的两个属性。】
这有点像SCATTER TO MEMVAR命令只不过使用了表单的自定义属性。作为面对对象方法的先进之处在于在内存中可以同时有多个记录。另外,这个方法建立的对象可以被传递到另外的方法,比如表单,另外,象我们将会看到的那样,还有com 对象。
下一步我们需要得到纪录并显示它们。添加一个列表框list1到表单上并使用生成器来选择客户表(Customer)作为数据源。如果碰到超过一个人同姓的情况,你可以把两个字段都选中。同样,你也可以查看和修改纪录,添加两个文本框Textbox1、Textbox2并把它们绑定到我们的纪录对象。
把Textbox1文本框的controlsource属性设置为:thisform.thisrec.firstname
把Textbox2文本框的controlsource属性设置为:thisform.thisrec.surname
记住thisrec是一个储存我们的记录的对象,在程序开始时我们把它清空了。
【原来属性还可以这么用!属性变成了对象,竟然还会有自己的属性!】
在列表框list1的Click方法中加入以下代码以向对象添入数据:
select customer
Scatter name thisform.thisrec
thisform.refresh()
That is it!现在你可以用建立的对象来对记录进行更改、比较等无论什么操作,但等你干完了以后,必须象下面一样把修改送回表中:
添加一个命令按钮Command1,设置它的Caption属性为:"Save"、Enabled属性为False。
回到list1的Click方法,添加下面一行代码:
Thisform.Command1.enabled = .T.
现在list1的Click方法代码应该是这样的:
Select customer
Scatter name thisform.thisrec
thisform.refresh()
thisform.Command1.enabled = .T.
在Command1的Click方法中加入以下代码: Command1.Click方法:Gather name thisform.thisrec
this.enabled = .F.
我想你已经理解了,可以添加你自己的"添加新纪录"按钮或"删除纪录"的按钮。下一步,我们将看一下怎样传递这些对象到别的方法。
传递对象到其他的方法和表单:
如果你已经照着第一步那么做了,那么你已经有了一个收集和更改纪录的表单,它通过使用一个放置纪录的对象来做到这一点。现在我们来看看怎样传递对象到另一个方法。尽管当对象对任何表单方法是可视的时,这种办法看起来没什么用。不过我们先来试着做一下,我们将给表单添加一个交换名和姓的自定义方法。
给表单添加一个名叫Swapfields的自定义方法,并输入以下的代码:
表单的 Swapfields 方法
LParameters RecObject
Local TempStore
TempStore = RecObject.Firstname
RecObject.Firstname = RecObject.Surname
RecObject.Surname = TempStore
添加一个命令按钮command2,设置它的Caption属性为Swap names、Enabled属性为False。
Comand2.Click方法
thisform.swapfields(thisform.thisrec)
this.enabled = .F.
[译者注:注意到了吗?向swapfields方法传递的是从属性变成对象的thisrec!玩了那么久的VFP,只听说过传递变量、数组、字符串的,没想到竟然还能传递对象!真是开了眼界了。]
在list1控件的Click方法代码中加入下面一行:
thisform.command2.enabled = .T.
List1的Click方法代码现在看起来应该是这样的:
Select customer
Scatter name thisform.thisrec
thisform.refresh()
thisform.Command1.enabled = .T.
thisform.Command2.enabled = .T.
现在让我们看看发生了什么:姓和名被交换了一圈,并且结果可以被储存。象我说过的那样,对这个简单的示例程序来说,这看起来没什么用,因为我们能够直接对 Swapfields方法中使用的对象进行操作。但是如果你要同时操作多个纪录,也许你在比较纪录并且你的表单上有两个或多个纪录对象。
那么用这种方法,这个表单自定义方法对任何一个对象而言都是相同的,并且你的命令按钮也可以对任何一个相关联的对象进行操作。只要字段相同,Swapfields方法始终不会在乎。你可以更进一步建立一个自定义方法同时对两个记录对象操作并同时发送结果。
传递对象到其他的表单
这里有更多的技巧。如果你看看我们的文本框对象,你将看到它们的ControlSource属性都被从我们的'thisrec'对象赋值。因为我们在文本框初始化之前已经让我们的对象分散(Scattered)了数据,所以这样做是正确的。这里我们在表单的Load方法中用Scatter name thisform.thisrec收集了数据,当我们调用另一个表单时,在新表单的文本框有控制源(ControlSource)以前我们不能对这些文本框做任何事。另外会发生一个错误并且新表单不能初始化。有许多办法可以解决这种情况,但你选择怎么做必须依情况而定。一种办法是让文本框的ControlSource为空。另外也可以把它们的值指向一个虚假的属性或者把它们当成一个直到表单的纪录对象已经被生成时才添加的一个容器对象的一部分。下面使用了第一种方法。
要开始下一步,建立一个新的表单,表单上有两个文本框和一个命令按钮,设置命令按钮的caption属性为'Swap Fields'。建立一个表单属性'recobject',它将被用来保存从初始表单传递过来的对象。最后,把表单设置为模式表单。
表单的Init事件中:
LParameters oRecObject
thisform.recobject = oRecObject
thisform.text1.controlsource = "thisform.recobject.firstname"
thisform.text2.controlsource = "thisform.recobject.surname"
在Init事件中,我们传递了纪录对象,现在它是这个表单的一个表单属性并且设置了文本框的数据源ControlSource。因为现在表单尚未激活,在这里不需要刷新表单。
下面是命令按钮的代码:
Command1.Click
Local Tempstore
Tempstore = thisform.recobject.firstname
thisform.recobject.firstname = thisform.recobject.surname
thisform.recobject.surname = Tempstore
thisform.release()
看起来这个表单(被调用表单)有自己的纪录对象。而实际上这是和调用它的表单使用的是同一个对象。我们现在来证明一下。编辑调用它的表单的Swap fields命令按钮的Click事件代码:
Command2.Click
&& thisform.swapfields(thisform.thisrec)
do form swapper with thisform.thisrec
this.enabled = .F.
thisform.refresh()
现在当表单运行时,如果按下了Swap fields命令按钮,将弹出新的表单,在这
个新表单上单击Swap fields命令按钮,这个表单将被释放。这个初始表单的字段已经被
交换了。