在狐表中,跨事件传值一般有这几种用法:
<!--[if !supportLists]-->1、 <!--[endif]-->在全局代码定义变量
狐表加载完成后可以使用,可以定义任意强类型的变量,不可以持久化(关闭项目后丢失),占用内存,不过性能是最好的。最大的缺点是全局代码改变必须重启项目,所以一般配合内部函数使用。
<!--[if !supportLists]-->2、 <!--[endif]-->定义全局变量
狐表加载完成后可以使用,可以定义任意类型的变量,不可以持久化,占用内存,使用性能在全局代码之后。可以随时定义变量而不需重启。不过对于复杂类型猜测应该是以Object引用而非强类型,故赋值和取值时应该有封箱和拆箱的过程,略微有性能损失。
<!--[if !supportLists]-->3、 <!--[endif]-->通过数据表
表加载后可以使用,对数据类型有限制,复杂数据类型需要序列化成字符串(一般为XML和JSON,或者自定义格式<这种狐表本身用的比较多,比如窗口模板>,必要时也可以进行加密,这也是狐表常用的)进行存储,可以持久化,占用内存。复杂数据类型存取需要序列化和反序列化,性能比封箱和拆箱损失更大。如果表没有加载,还要加上IO读写和网络传输的损耗。
<!--[if !supportLists]-->4、 <!--[endif]-->通过已经打开的窗口的控件
必须打开窗口才可以用,对数据类型有限制,复杂数据类型同样需要序列化才能存储,不可以持久化。一般应用在模式窗口对父窗口的操作上,反过来就有一定的操作难度了。
<!--[if !supportLists]-->5、 <!--[endif]-->通过配置文件(ini、XML、文本文件等)
即对磁盘文件进行操作,产生IO操作。需要把数据类型序列化成字符串存储,可以持久化。
<!--[if !supportLists]-->6、 <!--[endif]-->通过注册表
操作注册表,只能存储字符串,长度有一定的限制,可以持久化,重装系统会丢失。
<!--[if !supportLists]-->7、 <!--[endif]-->通过内部配置
使用“SaveConfigValue”存储,只能存储字符串,可以持久化,不过更新项目后值会被覆盖。
以上根据个人的喜好和开发的需要进行选择使用。
本文主要针对的是模式窗口的传值和取值,为什么,因为模式窗口没有打开就没有办法操作窗口里的控件,模式窗口打开后是线程阻塞的,没有关闭之前后续代码就无法执行,同样也就没有办法在窗口之外操作窗口里的控件。其它类型窗口,打开后直接操作其控件即可。
本文说的重点是查询窗口,比如自定义录入窗口这类的,这里以模式窗口为例,做成通用的窗口,里面的表格控件可以根据条件显示不同的数据表,以及选择后根据需要返回不同的值,那么这里的条件和返回值就要想办法获取了。
这里就以第一种用法做个简单的例子。
首先,在全局代码定义一个字典类型的变量存储条件和返回值,代码如下:
Public
_formData as Dictionary(Of string,Object)
这里采用键值化的字典是可以使得窗口传值适用于不同的窗口,键string存储窗口名称,值Object为窗口条件和返回值。
在项目事件Afteropenproject中进行初始化:
_formData = new
Dictionary(Of string,Object)
在内部函数定义一个通用的函数,对这个变量进行统一的操作,比如函数名Form_Data_Do,代码如下:
Dim formname As String = Args(0) '窗口名
Dim mode As Integer = Args(1) '1为赋值,2为取值,3为取值同时清空窗口返回值
Dim data As object '参数mode为1时,要赋值的数据
If Args.length > 2 Then
data = Args(2)
End If
If mode
= 1 Then '赋值
_FormData(formname)
= data
ElseIf _FormData.ContainsKey(formname) Then '取值
Dim value = _FormData(formname)
If mode = 3 Then _FormData(formname) = Nothing '取值后清空当前窗口返回值
Return value
Else
Return Nothing
End If
调用方法,比如有一个设置公众号消息模板的窗口,在消息模板中需要选择消息类型,而不同类型的公众号可用的消息类型是不一样的,代码如下:
Dim Filter = "类别='消息发送类型'"
Dim formname = "Pub_SelectForm"
Dim tData As new Dictionary(Of String,object)
tData.Add("TableName",
"字典表")
tData.Add("TableFilter",
Filter)
tData.Add("DataType",
0)
'tData.Add("Width", 600)
'tData.Add("Height", 500)
Functions.Execute("Form_Data_Do",
formname, 1, tData)
Forms(formname).Open
Dim retData = Functions.Execute("Form_Data_Do",
formname, 3)
If retData
IsNot Nothing Then
e.Sender.Value = retData("值")
End If
接着我们把这个模式窗口设计出来,比如名称“Pub_SelectForm”,界面如下:
此主题相关图片如下:1.jpg

具体代码看窗口设计,这里不详细说了。
在调用窗口,放个“DropDownBox”控件,按如下设置:
此主题相关图片如下:2.jpg

把上面的调用方法的代码放到,“ModalButtonClick”事件代码,运行看看效果。
我们再来测试用这个通用窗口来选择另外一个数据,比如发送消息的时候需要选择一个定义好的模板进行发送,“ModalButtonClick”事件选择模板的调用如下:
Dim formname = Functions.Execute("Pub_GetSelectForm")
Dim tData As new Dictionary(Of String,object)
tData.Add("TableName",
"消息模板")
'tData.Add("TableFilter",
Filter)
tData.Add("ColVisible",
"模板ID|100|模板用途|120|消息类型|60|模板内容|-1")
tData.Add("DataType",
0)
tData.Add("Width",
600)
tData.Add("Height",
500)
tData.Add("FormName",
"模板管理")
tData.Add("Title",
"选择模板")
Functions.Execute("Form_Data_Do",
formname, 1, tData)
Forms(formname).Open
Dim retData = Functions.Execute("Form_Data_Do",
formname, 3)
If retData
IsNot Nothing Then
e.Sender.Value = retData("模板ID")
End If
这样,一个简单的窗口传值和通用窗口的简单应用就完成了。
当然,不仅仅是模式窗口,其它类型的窗口也可以通过这种方式进行传值,
如果需要这个窗口还可以扩展一下,比如增加一个按钮,根据需要打开相应的管理窗口对查询窗口里面的内容进行动态修改,然后再进行选择,具体用法这里就不详细描述了,请参考例子。不过这个用法会产生一个小小的问题,就是如果在管理窗口中又用到了这个通用的窗口怎么办?狐表的窗口可是只能同时在一个地方出现的。一种解决方法就是,利用窗口模板创建多一个一样的通用窗口,当然窗口名称是不一样的。那么在调用通用窗口的时候就先判断一下,第一个通用窗口是否已经打开,如果打开了就调用第二个通用窗口,以此类推,我们可以创建多个相同的通用窗口。不过一般来说模式窗口2层甚至3层嵌套基本就够用的,如果再多就要考虑是否业务逻辑有问题了。
定义一个调用哪一个通用窗口的函数,代码如下:
If Forms("Pub_SelectForm").Opened
Then
Return "Pub_SelectForm2"
Else
Return "Pub_SelectForm"
End If