Dorado 5 : 1.2.5.DyanmicDropDown(动态下拉框) (RF2)

简述

DatasetDropDown的功能增强版,基本功能类似,不同点在于:
默认支持分批数据下载,从而改善大数据量的数据下拉框展示性能问题;
支持配置方式实现下拉数据的查询和快速定位功能;
显示效果如下图:

图表 5 DynamicDropDown
注意上图下拉框中,出现一个DatasetDropDown没有的编辑框以筛选功能按钮,这主要为了支持用户对下拉数据实现模糊查询功能,注意此处的模糊查询会利用dorado的引擎从服务器去对所有的数据实现筛选。
实现的机制参考dataset的flushData功能;
大部分情况下DatasetDropDown可以解决我们的开发问题,但是在某些特别的情况下,如下拉数据源的Dataset对象包含的数据量太大,必须分页下载,否则会使页面第一次加载耗费很长的时间。这也就是性能问题,关于性能方面的文章详细内容参考<<Dorado5 性能指南.doc>>.DynamicDropDown可以通过设定绑定dataset的分批下载功能实现高性能的下拉框。
同样针对数据量大的问题,虽然可以通过分批下载解决加载的性能问题,但是对于使用者来说依然存在一个问题,试想假如共有10000条数据,如果要让使用者通过自己的眼睛从DatasetDropDown中找到一条合适的数据是多么不可想象的一件事,10000条数据对于一个信息系统来说根本不算大,因此我们应该提供用户一种快速定位的功能,通常情况下这种功能都会以查询的方式提供。如图表4中,我们可以在下拉框窗体的编辑框中输入"国笠伟"并单击筛选功能按钮,就能定位到我们需要的记录上。
动态数据下拉框通过直接引用一个Server端的数据集构造下拉框中的数据. 动态数据下拉框与数据下拉框(DatasetDropDown)的区别在于数据下拉框会在页面打开时将下拉数据一次性生成到客户端, 而动态数据下拉框并不会在页面打开是下载任何数据,只有用户实际打开该下拉框时才会执行的数据下载.
由于数据已提前下载数据下拉框可以提供类似mapValue这样的功能, 但是它不能很好的适应下拉数据量较大的应用场景,同时过渡使用数据下拉框也可能造成页面效率的低下. 而动态数据下拉框则可以很好的适应大数据量的性能要求, 不会影响页面初次打开的速度,同时还可以提供动态数据筛选这样的功能.

使用

作为DatasetDropDown的一个功能增强组件,其使用和定义的方式就基本与DatasetDropDown对象相同,包括事件处理机制等。
但还是存在一些不同点

  • DynamicDropDown绑定的dataset对象不是来自于视图模型,而是来自于数据坞,至于数据坞中定义dataset的方式与视图模型几乎没有差别,定义好之后我们就可以通过其子节点DropDown 类型的Dataset对象来描述,设定其中的sourceModule指定数据坞,sourceDataset指定引用数据坞中的那个dataset对象

    <Control id="dropdown1" type="DynamicDropDown">
    <Dataset
    type="DropDown"
    sourceModule="sample.Contract"
    sourceDataset="datasetCustomer">
    <Fields />
    <Parameters />
    <Properties />
    </Dataset>
    <Parameters />
    </Control>

    该段xml配置文件在设计时可以通过studio中的向导窗口定义,如下图:
    选择DynamicDropDown的dataset子节点:

    图表 6 DropDownDataset
    找到属性sourceDataset的快捷按钮,并单击出现sourceDataset的选择向导:

    图表 7 选择数据坞中的一个Dataset
  • 在Dataset的相关文档中知道实现分批数据下载是通过dataset的pageSize属性实现。DynamicDropDown是通过DropDownDataset指定的,如下:

    <Control
    id="dropdownEmployee"
    type="DynamicDropDown"
    fixed="true">
    <Dataset
    type="DropDown"
    sourceModule="sample.HR"
    sourceDataset="datasetEmployee"
    pageSize="20">
    <Fields>
    <Field name="employee_id" dataType="string">
    <Properties />
    </Field>
    <Field name="employee_name" dataType="string">
    <Properties />
    </Field>
    </Fields>
    <Parameters />
    <Properties />
    </Dataset>
    <Parameters />
    <Events />
    </Control>

    上面的代码设定了DropDown类型的Dataset节点的pageSize为20。DynamicDropDown的使用都是通过这个属性定义分批下载数据中的pageSize特性的。
  • 另外值得关注的是数据筛选功能

在实现数据筛选功能时千万不要忘本,之所以这么说是因为无论采用什么技术,最终的数据过滤功能都是通过DAO或DBDataset完成的,也就是说我们必须得在DAO或则DBDataset中有所设定,当它们支持数据筛选功能时,我们在下拉框中提供给用户的筛选功能才有意义。
下面我们以AutoSqlDataset为例,举例说明图表4中员工姓名的筛选功能实现:
第一步:配置AutoSqlDataset,使它支持数据过滤功能,doradosample中的该dataset定义如下:

<Dataset id="datasetEmployee"
type="AutoSql"
originTable="employee">
<Fields>
<Field name="employee_id"
originField="employee_id"
table="employee">
</Field>
<Field name="employee_name"
originField="employee_name"
table="employee">
</Field>
<MatchRules>
<MatchRule originField="employee_name"
table="employee"
operator="like"
dataType="string"
value=":employee_name"
escapeEnabled="true" />
</MatchRules>
</Dataset>

在该配置中添加了AutoSqlDataset的BaseMatchRule,实现员工姓名的模糊查询功能,关于BaseMatchRule的详细使用请参考AutoSqlDataset章节。
第二步:
修改DynamicDropDown的xml配置,代码如下:

<Control id="dropdownEmployee"
type="DynamicDropDown"
filterParameter="employee_name">
<Dataset type="DropDown"
sourceModule="sample.HR"
sourceDataset="datasetEmployee"
pageSize="20">
<Fields>
<Field name="employee_id" dataType="string">
<Properties />
</Field>
<Field name="employee_name" dataType="string">
<Properties />
</Field>
</Fields>
</Dataset>
</Control>

当设定了DynamicDropDown的filterParameter属性后,下拉框打开后会自动的产生一个编辑框以及筛选按钮,并且默认的按钮单击事件自动执行如下的脚本代码:

var parameterValue = editor.value;
if (parameterValue!='') {
parameterValue="%"parameterValue"%";
dataset.parameters().setValue("employee_name", parameterValue);
dataset.flushData();
}

利用dataset的页面不刷新技术,后台的AutoSqlDataset在接收到新的employee_name参数值之后,重新执行一次查询,并显示在DynamicDropDown的下拉列表中。
在前面两步完成的基础上再来看DynamicDropDown对象的另一个与数据筛选有关的属性filterOnOpen,该属性用来指定DynamicDropDown在第一次打开时是否要根据被绑定下拉框的编辑框中获取值并作为参数直接执行筛选动作,下拉列表中只显示筛选之后的数据。

常用技巧

基本技巧参考ListDropDown的常用技巧

利用DynamicDropDown对象的parameters给数据坞中的dataset对象传递参数

由于DynamicDropDown本身的特殊性,导致无法在脚本中获取它所引用的Dataset对象,因此当需要给这个所引用的Dataset对象传递参数时我们就不能通过如下的代码实现(DatasetDropDown可以):

var ds = dropdown.getDataset();
ds.parameters().setValue("branch_id", "D3");//动态设置查询参数
ds.flushData();//使用XMLHttp技术将查询参数上传到服务器,并重新获取数据到客户端
ds.refreshControls();

在DynamicDropDown的使用中,可以通过它提供的parameters实现这个处理,上面的代码修改为如下代码即可:

dropdown.parameters().setValue("branch_id", "D3");//动态设置查询参数
dropdown.setCachable(false); //禁止缓存,以便dropdown下次打开时自动的根据新设定的参数重新刷新下拉列表中的数据

DynamicDropDown运行时会自动的将自身的parameters中的内容复制到数据坞中的Dataset的parameters中,从而间接的实现对Dataset的parameters的赋值处理。

如何根据其它字段中值的变化动态改变记录集下拉框中的内容

我们可在指定字段所属dataset对象的afterChange事件中

switch (field.getName()) {
case "field1":
dropdown.parameters().setValue("branch_id","D1");//动态设置dropdown的parameters信息
dropdown.setCachable(false);//禁止缓存,以便dropdown下次打开时自动的根据新设定的参数重新刷新下拉列表中的数据
break;
}

动态编程

在服务器段获得View(视图模型)中定义的DynamicDropDown,并动态它的属性

protected void initControls() throws Exception {
super.initControls();//系统默认函数,注意保留
DynamicDropDown dropdown1= (DynamicDropDown)getControl("dropdown1");
dropdown1.setFixed(true);
dropdown1.setReadFields("dept_id,dept_name,branch_id");
dropdown1.setWriteFields("field1,field2,field3");
}

在上面的代码中可以看到通过实现类提供的getControl函数获得我们需要的组件对象,所需要的就是给它一个DynamicDropDown对象的id,注意开发时我们建议您直接在View的设计中添加一个DynamicDropDown组件,并指定引用的Dataset对象,这样我们就可以在initControls方法中通过getControl方法获得这个DynamicDropDown对象,并利用该对象提供的API进行各种设定和初始化的工作,如DynamicDropDown的setReadFields,setWriteFields方法。

主要属性说明

属性

说明

cachable

是否允许缓存,DynamicDropDown采用的是延迟数据加载技术,如果用户在一个页面上会对该下拉框操作多次,就建议使用缓存技术。提高操作效率。

filterOnOpen

是否在下拉框打开的时候就执行过滤操作,默认为false

filterParameter

与filterOnOpen配合使用,如果filterOnOpen为true,该下拉框打开时会自动从下拉框绑定的编辑框中的值作为下拉框的filterParameter指定的参数转换到dropdown的parameters中,并刷新下拉框中的数据,作过滤。该属性的使用还需要dynamicDropDown引用的dataset对象后台过滤功能的支持才能真正起作用

openMode

打开下拉框的方式:
Dropdown:下拉框方式
SubWindow:子窗口方式

startWithEmptyRecord

是否在下拉列表的第一行加入一条空记录,主要作用是清空绑定下拉框的编辑框在只读状态下的数据清空功能

warmUpDelay

warmUpDelay表示自动预热的延时时间。
由于此两类下拉框都是由一个独立的页面构成的,打开一个此类下拉框相当于请求一个页面。因此在第一次开打时可能会有明显的停顿感。为了改善用户体验,我们可以在用户操作此类下拉框之前对其经行预热。
注意:此处延时时间的单位为0.1秒,即warmUpDelay=20表示两秒。如果warmUpDelay=0表示不启用自动预热功能。

主要事件说明

参考ListDropDown的主要事件说明
参考DatasetDropDown的主要事件说明

CSS说明

参考ListDropDown的css说明