专利名称::一种表单系统数据源数据绑定方法
技术领域:
:本发明属于数据绑定领域,特别是涉及数据集与控件的关联,包括数据集字段元素与控件的绑定方法以及绑定关系的维护、存储和还原。
背景技术:
:数据绑定,是建立数据对象和控件之间的映射机制。数据绑定,传统上分为静态和动态绑定,也分为简单绑定和复杂绑定。静态绑定中绑定模型是固定的,数据绑定建立后就不再改变。动态绑定,模型和视图之间都可能随时有信息的改变,绑定需要动态的维护。简单绑定是指单值映射,一个控件绑定到一个数据字段元素。复杂绑定是一对多、多对一及多对多的映射,一个控件可以关联多个数据集字段元素,一个数据集字段元素关联多个控件,以及多个控件和多个字段元素的关联。当前,数据绑定技术包含两个方面一是绑定关系的建立。模型和控件的绑定,有手动绑定方法,通过函数把模型的属性绑定到控件的属性,及控件属性设置到模型属性;也有命名规则法,规定名称映射规则,比如反射方法和设置配置文件等。二是通知机制的建立。模型更改后,通知控件属性的改变;控件属性改变,通知模型改变。在模型中采用事件注册机制,属性改变后,发布通知给注册事件,由注册事件触发视图的改变;视图改变通过触发的事件,设置值到模型中。本发明涉及的问题是表单系统中数据集与控件的绑定。数据集是一种数据结构,是对数据源结构化操作(査询、更新和修改等操作)后所生成的对象的描述,包含结构化操作语句及解析操作后生成的结果字段和变量字段子对象。当数据集和控件绑定后,通过浏览表单可以获取绑定的数据集字段的数据源数据,使数据源数据通过控件展示出来。比如数据库sql语句selectname,addressfrominformation通过数据集对象化后包含语句、name和address属性及其类型信息。把name字段和控件text名称属性绑定,用户就可以通过浏览表单获取数据库数据源中information表name字段值。数据集可以看成是虚拟的数据集合,数据集与控件的绑定,不涉及到物理数据操作,绑定信息指明控件获取要设置或者展示的数据的位置。复杂的表单设计,数据集字段元素和控件的绑定操作非常的频繁。目前数据集字段元素和控件的绑定方法是将数据集字段元素和控件属性分别进行绑定,其绑定关系单一,每个数据集字段元素和控件模型元素都要建立绑定关系,且绑定关系储存于控件模型中。例如将一个数据集字段元素与控件进行绑定后所生成的绑定关系对象,便储存于控件模型中。这种方法的主要缺陷为(1)绑定关系不灵活。每个控件模型元素和每个数据集字段元素都要建立绑定关系。比如一个复合控件Table模型,里面的每列都必须要和数据集元素建立绑定关系。这样设计表单的操作次数的量就很大。如果一个Table有10列,就得进行IO次绑定操作。(2)绑定关系建立后,储存于控件模型中,绑定关系与数据集丢失了直接的关联信息。当数据集字段元素变化时,需要取消与变化元素相关的绑定关系。由于绑定关系存在于控件模型中,取消绑定关系就得对整个表单的控件进行搜索,査看每个控件是否有与变化元素相关的绑定关系,如果是复合控件还得对复合控件子控件的绑定关系进行搜索,如果有就取消。要删除数据集时,也要取消所有与这数据集关联的绑定关系。如果表单复杂,包含的控件数目很多,每次数据集的变化都要对控件进行穷举搜索,消耗大量时间。比如一个表单包含100个控件,数据集变化元素有5个,一次变化就要进行500次搜索。在表单设计中,数据集字段元素和控件之间绑定关系的变化是频繁的,这样就会消耗大量的搜索时间。特别对于处理海量数据的服务器,其程序执行效率慢的问题就会凸显,不能满足目前快速有效处理大量数据的需要。针对目前复杂表单系统设计中存在的问题,本发明提出了一种新的数据绑定办法,通过这种方法实现了数据源和控件的动态绑定,有效的解决了复杂表单设计中绑定关系建立的操作量大和数据集变动引起的搜索时间长的问题。
发明内容本发明通过如下方法实现数据源和控件的动态绑定,以解决复杂表单设计中绑定关系建立操作量大和数据集变动引起的搜索时间长的问题。数据源数据用操作语句(比如SQL等)描述,对操作语句进行解析,转换为数据集。数据集包含数据源的字段名称和字段类型。控件是表单的显示元素,控件都有对应的模型,复合控件包含其他子控件。1.绑定关系的设置绑定关系是数据集字段元素与控件的关联关系。绑定关系具体用绑定关系对象进行描述,绑定关系对象为一个二元组,包括绑定关系类型和绑定关系值,即表示为(绑定关系类型,绑定关系值)。本发明中绑定关系可有三种类型值、二元关系表和匹配模式。三种类型可用字符串、数值或其它符号进行表示。如果绑定关系类型为值,即单值绑定,此数据集字段元素即为绑定关系值;如果绑定类型为二元关系表,其中,所述二元关系表用于设置数据集中字段与控件的对应关系,例如,数据集与表的绑定,可以设置数据集中字段名称和表头字段名称的对应关系,将所有对应关系建立为关系表,绑定关系值即为此关系表对象;如果绑定类型是匹配模式,其中,匹配模式是定义规则,作为绑定元素和控件属性的关联准则,应用匹配模式,可以自动建立数据集字段元素和控件的绑定,比如设置名称相同的匹配规则,数据集字段名称和复合控件子控件名称相同的就会自动绑定,绑定关系值即匹配规则,如字符相同匹配和忽略大小写的字符相同匹配等规则。本发明对绑定分为简单绑定和复杂绑定。简单绑定是单一映射,如控件和数据集字段元素的绑定,可通过关联控件和数据集子元素来实现,即上述单值绑定情况。对于复杂的绑定,如控件是复合控件,控件多个子元素要和数据集字段元素绑定,可以通过设置绑定关系,生成上述绑定关系类型为二元关系表或匹配模式的绑定关系对象。2.全局绑定关系矩阵的建立在本发明中采用全局绑定关系矩阵储存绑定关系,全局绑定关系矩阵为一个二维数组。将具有绑定关系的数据集字段元素依次转化为连续的整数(字段ID)作为矩阵的列号,将具有绑定关系的控件依次转化为连续的整数(控件ID)作为矩阵的行号,然后将绑定关系对象设置为行列对应处数组元素的值。其中,所述的数据集字段元素和控件的标识可用字符串、数值或其它符号进行表示。在建立过程中,找到字段ID所在的行,如果不存在则在全局绑定关系矩阵中新建行;再找到控件ID所在的列,如果不存在则在全局绑定关系矩阵中新建列;把绑定关系对象设置行列对应处数组元素的值。同样,也可以将字段ID作为矩阵的行号,将控件ID作为矩阵的列号,然后将绑定关系对象设置为行列对应处数组元素的值。当表单从xml文件反序列化为模型的时候,要复原全局绑定关系矩阵。复原过程为如控件xml标记模型化中,发现绑定标记,把绑定标记反序列化为绑定关系对象,绑定关系xml标记到绑定关系对象的转化,只需要把绑定关系类型和绑定关系值填入绑定关系对象即可,然后依上述方法将绑定关系对象填入全局绑定关系矩阵中。3.全局绑定关系矩阵的维护全局绑定关系矩阵建立以后,数据集字段元素与控件的绑定关系变化便可以通过改变全局绑定关系矩阵来实现。当一个新的数据集字段元素要和控件建立绑定关系,只需要注册新的列或行,再将绑定关系对象填入全局绑定关系矩阵即可。当一个数据集字段元素和多个控件属性建立绑定关系,数据集删除掉绑定字段元素后,绑定的取消只需注销全局绑定关系矩阵中的字段元素列或行的值。当建立绑定关系的控件,要绑定到其他数据集字段元素,只需取消原有的绑定关系,用新的绑定关系对象填到新的字段元素与控件的对应位置。对于控件的变化也是同样的,比如删除掉某个控件,则与其相关的绑定关系都会失去作用。比如,修改数据集DataSetl中的数据源数据库sql语句为selectaddressfrominformation,数据集中只有address为可绑定元素。原有的绑定元素name与控件的绑定的取消,只需要在全局绑定关系矩阵中搜索与数据集有绑定关系的控件,找到绑定关系后取消掉也存在的name到控件的绑定关系,而不用从所有控件中进行査找。4.表单及绑定关系的存储数据绑定操作完成后,表单要从内存存储到物理介质上。存储过程为如表单序列化元素为控件,且控件在全局绑定关系表中存在绑定关系,则取出绑定关系对象,序列化后存储于相应控件。采用全局绑定关系矩阵储存绑定关系使得绑定实施的操作十分方便,只需要从全局绑定关系矩阵读取相应的绑定关系对象便可实施相应的绑定,可编写一个函数或类对象对全局绑定关系实施统一绑定,不需要就具体的绑定分别编写绑定代码,极大地减小了编程操作量,并且能更有效保证绑定关系的准确操作。而且,该方法的另一个有益效果是显著地提高程序运行效率。复杂的表单设计,数据集和控件的绑定操作非常的频繁,全局绑定关系矩阵的维护就变得非常重要。当绑定关系发生变化时,通过该方法设计的表单系统不再需要重新搜索控件的绑定信息,只需要更新全局绑定关系矩阵即可,解决了复杂表单中绑定关系变动引起的搜索时间长的问题。图1数据集与控件绑定模型图2全局绑定关系矩阵维护模型图3绑定关系存储模型图4绑定关系还原模型具体实施例方式下面结合附图举例说明本发明的具体实施方式。1.绑定关系在xml文件中的存储在本具体实施方式中,将本发明中三种绑定关系——值、二元关系表和匹配模式分别用字符串Value、Table和Match表示。在Match类型中用字符串Equal和EqualIgnoreCase分别表示字符相同匹配和忽略大小写的字符相同匹配。在本具体实施方式中,用xml文件存储绑定关系,绑定关系存储说明如图3。对于简单绑定,例如要将Text类型的控件textl和数据集datasetl中字段元素name进行绑定,绑定关系对象为(Value,name),存储到控件时xml文件为<TextID="textl",Content=""><BindID="datasetl"/><BindRelationType=,,Value,,,Relationname=,,inforValue,,〉name</BindRelation></Text>对于复杂绑定,如果绑定关系是二元关系表,此时绑定关系类型为Table,绑定关系对象为(Table,映射表对象)。映射表对象用Map数据结构表示,存储映射对。比如将数据集datasetl中两个字段元素(name,address)和表格中(名称,地址)绑定,存储到控件时xml文件为<TableID="tablel"><TRname^'名称"/〉<TRname^,地址"/〉<BindID="datasetl,7><BindRelationType=,,Table",Relationname=,,inforTable"〉<maping〉<IDl>name</IDl>〈ID2〉名称々ID2〉</maping><maping><ID1>address</ID1><ID2〉地址々ID2></maping〉</BindRelation></Table>如果绑定关系是匹配模式,此时绑定关系类型为Match,绑定关系对象为(Match,具体匹配规则)。如果具体匹配规则具体是忽略大小写的字符相同匹配,则绑定关系对象为(Match,EqualIgnoreCase)。比如数据集datasetl中字段元素(name,address)和表格中(Name,Address)绑定,存储到控件时xml文件为<TableID="tablel"><TRname=,,Name,7〉<TRname=,,Add應,V〉<BindID="datasetl,,/〉<BindRelationType="Match",Relationname="inforMatch">EquallgnoreCase</BindRdation></Table>2.绑定关系从xml文件反序列化为绑定关系对象模型当绑定关系类型为值,即单值绑定时,绑定关系值即相应字段元素,在本实施例中用字符串表示;当绑定关系类型为匹配模式时,绑定关系值为具体匹配规则,即上述的字符相同匹配、忽略大小写的字符相同匹配或其他规则,在本实施例中用字符串表示;当绑定关系类型为二元关系表时,绑定关系值为关系表对象,在本实施例中用字符串表示。然后从xml文件中获取绑定绑定信息转化为绑定关系对象。例如,可在Java语言中通过建立如下绑定关系对象模型来实现-packagedataBind;importjava.util.HashMap;publicclassBindRelation{//绑定类型publicenumtype{Value,Table,Match};〃绑定名称Stringname;//绑定类型typerelationType;〃如果是Value或者Match类型的,存储值Stringvalue;//如果是Table类型的,存储绑定对HashMap<String,String〉tableValue;〃把xml元素bindRelation转换为BindRelation对象BindRelationconvertToRelation(org.dom4j.ElementbindRelation){name=bindRelation.attributeValue("Relationname");〃value类型的转换if(bindRelation.attribute("Type").equals(type.Value)){relationType=type.Value;value=bindRelation.getTextO;〃表类型的转换elseif(bindRelation.attribute("Type").equals(type.Table)){relationType=type.Table;for(Objectobject:bindRelation.elements()){org.dom4j.Elementelement=(org.dom4j.Element)object;StringID1=element.elementText("ID1");StringID2=element.elementText("ID2");tableValue.put(IDl,ID2);〃匹配类型的转换elseif(bindRelation.attribute("Type").equals(type.Match)){relationType=type.Match;value=bindRelation.getText();returnthis;3.全局绑定关系矩阵的建立及维护当表单从xml文件反序列化为模型的时候,要复原和建立全局绑定关系矩阵。如图1图4所示,字段ID和控件ID分别作为矩阵的列号和行号,绑定关系对象作为行列交叉处数组元素的值。建立好绑定关系后,把字段ID、控件ID和绑定关系对象注册到全局矩阵。找到字段ID所在的行,如果不存在则在全局矩阵中新建行;再找到控件ID所在的列,如果不存在则在全局矩阵中新建列;把绑定关系ID填入行列对应处。复原过程为首先建立绑定关系全局矩阵对象。对控件xml标记进行模型化,发现绑定标记,把绑定关系标记对象化为绑定关系对象,填入全局矩阵中控件标记ID和绑定标记ID对应处。控件ID和绑定ID都可由控件xml标记获取,绑定关系xml标记到绑定关系对象的转化,只需要把绑定类型填入对象的类型属性,绑定名称填入对象的名称属性,值或者匹配字符串填入对象的值属性,映射对填入map对象。如下表单XML文件,<DataSetname="datasetl"〉<GolumnName>name</GolumnNam6〉<ColumnName>address</ColumnName></DataSet〉<TextID="textl",Content=""><BindID="datasetl,7><BindRelationType="Value",Relationname="text1Bind"〉name</BindRelation></Text>复原过程为建立全局绑定关系矩阵对象matrix,对控件textl进行模型化,发现绑定标记Bind,把绑定关系BindRelation标记转换为绑定关系对象二元组(Value,name)填入datasetl禾Btextl对应处。数据绑定关系,在表单设计中是可变。绑定关系建立后,可能被取消或者建立新的关系。需要对全局绑定关系矩阵进行维护。全局矩阵的动态维护如图2,具体描述如下-全局绑定关系矩阵有全局标志行标r和列标c,每行和每列的头部又另有index标志。全局标志表示当前可用的行和列的数量;index标志表示本行或者列的绑定关系数。对全局绑定关系矩阵的操作维护如下(1)注册绑定关系。如果分配了行或者列,则全局行标或者列标减1;填入绑定关系不是替换掉原有的绑定关系,对应的行或者列index增加1;检测全局行标或者列标,如果有等于o,则压縮全局矩阵,全局矩阵分配固定行数和列数的空余,设置全局行标和列标数。(2)注销绑定关系。如果是整行或者整列注销,则设置行或者列的index为0;如果是注销某个绑定关系,对应行或者列index减少1。(3)压縮全局矩阵。检测行标和列标,如有为0的,则把本行或者本列删除。这里全局标志显示剩余的行或者列,可以作为压縮矩阵的标志;行标或列标index,表示本行或者列是否有效,这样在全局矩阵压縮前,可以不用对矩阵大小进行变化。例如,以上过程可在Java语言中通过如下代码来实现//新建绑定关系存储矩阵Matrixmatrix=newMatrix();〃传入的是Text的xml节点,根据节点获取ID属性值StringcontrolName=TextXml.attributeValue("ID");〃获取Text中绑定的数据集的名称StringbindName=TextXml.element("Bind").attributeValue("ID");//新建绑定关系BindRelationbindRelation=newBindRelation();〃把xml形式的绑定关系转换为绑定关系对象bindRelation.convertToRelation(TextXml.element("BindRelation"));〃把绑定关系存入控件名称和数据集对应处matrix.put(bindName,controlName,bindRelation);其中,Matrix类为如下代码packagedataBind;importjava.util.Has固ap;importjava.util.Stack;publicclassMatrix{〃存储绑定关系对象,用二维数组表示矩阵BindRelation[][]store;〃记录每行的indexint[]rowlndex;〃记录每列的indexint[]columnlndex;〃总的行数introwj〃总的列数intcolumn;〃存储具体的未使用的行或者列的标号Stack<Integer>rowUnUsed=newStack<Integer>();Stack<Integer>columnUnUsed=newStack<Integer〉();//存储标志名和行或者列的对应关系,标志名是字段名称或者控件名称HashMap<String,Integer〉idMap=newHashMap<String,Integer〉();〃初始化存储publicMatrix(){〃TODOAuto-generatedconstructorstubstore=newBindRelation[10][50];row=10;column—50;rowlndex=newint[10];columnlndex=newint[50];for(inti=0;i<10;i++)rowUnUsed.push(newInteger(i));for(inti=0;i<50;i++)columnUnUsed.push(newInteger(i));〃初始化存储publicMatrix(introw,intcolumn){〃TODOAuto-generatedconstructorstubstore=newBindRelation[row][column];this.row—row;this.column=column;rowlndex——newint[row];columnlndex=newint[column];for(inti=0;i<row;i++)rowUnUsed.push(newInteger(i));for(inti=0;i<column;i++)columnUnUsed.push(newInteger(i));〃分配新的行publicbooleannewRow(Integerrowld){if(rowUnUsed.isEmpty(》returnfalse;else{rowld=rowUnUsed.pop();returntrue;//分配新的列publicbooleannewColumn(Integercolumnld){if(columnUnUsed.isEmpty())returnfalse;else{columnld=columnUnUsed.pop();returntruej//存储绑定关系,存储成功返回trae,没有空间存储返回falsebooleanput(StringDataSetId,StringTextld,BindRelationrelation){booleanisNull=true;//己经有字段和控件的,覆盖以前的绑定关系if(idMap.containsKey(DataSetld)&&idMap.containsKey(TextId)){if(store[idMap.get(DataSetld)][idMap.get(Textld)]!=null)isNull=false;store[idMap.get(DataSetld)][idMap.get(Textld)]=relation;//第一次建立的绑定,需要分配新的位置存储绑定关系对象elseif(!idMap.containsKey(DataSetld)&&idMap.containsKey(TextId))Integerrowid=0;if(newRow(rowid)){idMap.put(DataSetId,rowid);store[idMap.get(DataSetld)][idMap.get(Textld)]=relation;}elsereturnfalse;elseif(idMap.containsKey(DataSetld)&&!idMap.containsKey(TextId))Integercolumnid=0;if(newRow(columnid)){idMap.put(DataSetId,columnid);store[idMap.get(DataSetld)][idMap.get(Textld)]=relation;}elsereturnfalse;elseif(!idMap.containsKey(DataSetld)&&!idMap.containsKey(Textld))Integercolumnid=0;Integerrowid=0;if(newRow(rowid)&&newRow(columnid)){idMap.put(DataSetId,rowid);idMap.put(DataSetId,columnid);store[idMap.get(DataSetld)][idMap.get(Textld)]=relation;}elsereturnfalse;〃如果是新增的存储,行和列的index分别加1if(isNull){rowIndex[idMap.get(DataSetId)]++;columnIndex[idMap.get(TextId)]++;returntrue;〃撤销绑定关系booleanredraw(StringDataSetId,StringTextid){if(idMap.containsKey(DataSetld)&&idMap.containsKey(TextId)){if(store[idMap.get(DataSetld)][idMap.get(Textld)]!=null){store[idMap.get(DataSetld)][idMap.get(Textld)]=null;〃撤销后,行和列的index分别减1rowIndex[idMap.get(DataSetld)]—;columnlndex[idMap.get(Textld)]—;returntruejreturnfalse;〃压縮,如果有行标或者列表为0的,又不再未分配的行或者列里,则在未分配的行或者列里添加voidcompressO{for(inti=0;i<row;i++){if(rowlndex[i]—0)if(!rowUnUsed.contains(newInteger(i)))rowUnUsed.push(newInteger(i));for(inti=0;i<column;i++){if(columnlndex[i]—画0)if(!columnUnUsed.contains(newInteger(i)))columnUnUsed.push(newInteger(i));}权利要求1.一种应用于表单设计的将数据集数据绑定于控件的方法,包括如下步骤(1)构建绑定关系对象,该绑定关系对象包括数据与控件的绑定类型以及该绑定类型对应的绑定元素信息;(2)建立数据集,同时建立全局绑定关系矩阵,全局绑定关系矩阵为一个二维数组,用于储存全部绑定关系,将具有绑定关系的数据集字段元素的表示符号依次转化为连续的整数作为矩阵的列号或行号,将具有绑定关系的控件的标识依次转化为连续的整数作为矩阵的行号或列号,然后将绑定关系对象依次设置为行列对应处数组元素的值;(3)数据集字段元素与控件的绑定关系变化通过改变全局绑定关系矩阵来实现绑定关系的取消可通过注销全局关系表中相应行或列的值来实现,新的绑定关系的建立可通过新建行或列并填入相应绑定关系对象来实现,绑定关系的变更通过将新的绑定关系对象覆盖原有绑定关系对象来实现;(4)绑定的实施通过读取全局绑定关系矩阵中相应绑定关系对象的绑定信息来实现。2.根据权利要求1所述的将数据集数据绑定于控件的方法,其特征在于,所述字段元素和控件的表示符号为字符串或数值。3.根据权利要求2所述的将数据集数据绑定于控件的方法,其特征在于,该方法还包括将全局绑定关系矩阵的绑定关系对象存储于xml文件的步骤。4.根据权利要求1至3中任一权利要求所述的将数据集数据绑定于控件的方法,其特征在于,所述数据与控件的绑定类型是指单值绑定,所述绑定元素信息为绑定关系所对应的数据字段表示符号。5.根据权利要求4所述的将数据集数据绑定于控件的方法,其特征在于,所述单值绑定用字符串或数值表示,所述数据字段表示符号为字符串或数值。6.根据权利要求1至3中任一权利要求所述的将数据集数据绑定于控件的方法,其特征在于,所述数据与控件的绑定类型是指将数据字段与控件属性进行二元对应的绑定,所述绑定元素信息为所有相互对应的数据字段与控件的表示符号。7.根据权利要求6所述的将数据集数据绑定于控件的方法,其特征在于,所述将数据字段与控件属性进行二元对应的绑定用字符串或数值表示,所述数据字段与控件的表示符号为字符串或数值。8.根据权利要求1至3中任一权利要求所述的的将数据集数据绑定于控件的方法,其特征在于,所述数据与控件的绑定类型是指将数据字段与控件属性进行匹配的绑定,所述绑定元素信息为数据字段与控件属性的匹配规则。9.根据权利要求8所述的将数据集数据绑定于控件的方法,其特征在于,将数据字段与控件属性进行匹配的绑定用字符串或数值表示,所述数据字段与控件属性的匹配规则用字符串或数值表示。10.根据权利要求9所述的将数据集数据绑定于控件的方法,其特征在于,所述数据字段与控件属性的匹配规则为字符相同匹配和忽略大小写的字符相同匹配。全文摘要本发明提供一种表单系统数据源数据绑定方法,具体是一种用于表单设计中将数据集中数据绑定于控件的方法,以解决复杂表单设计中绑定关系建立操作量大和数据集变动引起的搜索时间长的问题。该方法利用包含绑定关系类型和绑定关系值的绑定关系对象表示绑定关系,通过设置全局绑定关系矩阵管理绑定关系,方便了绑定实施的操作,提高了表单程序运行效率。文档编号G06F17/30GK101566948SQ20091009924公开日2009年10月28日申请日期2009年5月26日优先权日2009年5月26日发明者健吴,吴朝晖,尹建伟,莹李,杨显发,邓水光申请人:浙江大学