Dorado 5 : 1.2.6.CustomDropDown(自定义下拉框) (RF2)

简述

在前面提到的各种类型的下拉框,都有自己的实现方式,尤其是对于页面展示内容作了默认的规定,通过修改属性或则编码可以进行局部的调整。事务总是存在两个方面的,配置简单了,扩展就变得比较难,为了使下拉框中的展示内容更容易得让开发人员去定制,例如在系统中需要下图中树形结构的下拉列表:

图表 8 CustomDropDown
上图中的下拉列表是无法通过以上介绍过的任何一种下拉框实现的。
Dorado提供CustomDropDown,它可以引入一个独立的dorado的jsp页面,作为下拉框的展示内容。这样开发人员就可以利用现有的各种JSP开发技术实现自己想要的一个展示页面,开发完成之后我们再将它调整并作为CustomDropDown的绑定JSP。如上图的树实际上是一个独立的jsp页面。

使用

自定义下拉框支持用户扩展自己的下拉框,实现dorado中默认提供的各种下拉框所不具有的功能. 这种下拉框的扩展是通过一个path属性绑定到一个可以由用户任意定制的下拉JSP上, 按照这种方式我们可以非常灵活的开发出各种类型的下拉页面并最终将其封装为一个自定义下拉框.
同时下拉框还提供了onSelect事件以及beforeOpen事件, 方便开发人员在下拉框打开以及选择的过程中人工控制系统默认的动作.例如数据处理、界面显示等等.
需要注意的是被下拉框绑定的页面需要按照一些特定的规范来开发. 它和传统dorado页面的区别很小,我们可以很容易地把一个dorado页面改造为自定义下拉框页面.
自定义下拉框用于解决用户对下拉界面有相对复杂的要求,当开发人员无法通过前面提供的几种下拉框解决问题时,可以创建一个dorado的下拉框页面,在该页面中使用的开发技术与普通的dorado页面几乎一致。但是我们可以利用dorado页面开发的强大功能设计一个功能更丰富的页面放在下拉框中。
自定义下拉框的开发包含两部分内容:

  • 下拉框页面设计
  • 下拉框设计

以下详细解释其中的开发技术
下拉框页面设计
和普通dorado页面比较而言,下拉框页面的设计有两个不同之处:
1.视图模型不同,创建的视图模型的时候我们要选用CustomDropDown ViewModel

图表 9
通过该种方式新建的视图模型在xml的描述上有些特殊之处

<?xml version="1.0" encoding="UTF-8"?>
<view clazz="com.bstek.dorado.view.control.dropdown.CustomDropDownViewModel">
<Datasets></Datasets>
<Controls></Controls>
</view>

下拉框页面提供了一个默认的实现类,如果你还想自定义实现类就必须扩展CustomDropDownViewModel.
2.当完成下拉框页面的操作之后,通过dorado提供的DropDown.closeFrame(Object obj)函数返回一个任意类型的对象给调用下拉框的主界面,告之当前下拉框页面的操作信息,如范例
http://www.bstek.com/dorado5/control/dropdown-employee-tree.jsp中树节点的单击事件中的代码,如下:

var node = treeHR.getCurrentNode();
if (node != null && node.getLevel() == 3) {
DropDown.closeFrame(node.getRecord());
}
}

该代码中返回一个record对象给主界面.
下拉框对象定义方法:
定义好下拉框引用的页面之后,我们就在主界面上定义一个CustomDropDown对象,xml定义如下:

<Control id="dropdownCustom"
type="CustomDropDown"
path="dropdown-employee-tree.jsp"
readFields="employee_id,employee_name"
writeFields="employee_id,employee_name"
width="200" height="250" fixed="true" warmUpDelay="20" />

其中最主要的就是path属性,自定义下拉框通过path关联到被引用的JSP页面,如果被引用的页面通过DropDown.closeFrame()方法返回的是Record对象,就可以通过readFields属性从返回Record中读取字段数据,并按照writeFields写入目标dataset,如果DropDown.closeFrame()返回的不是一个record对象,则我们需要在CustomDropDown的onSelect事件中实现具体的逻辑。
如被引用页面关闭页面时,通过如下代码用CustomDropDown.closeFrame()方法返回自定义的信息:

var records = new Array();
var record = datasetDegree.getFirstRecord();
while (record != null) {
if (record.getValue("select")) {
records.push(record);
}
record = record.getNextRecord();
}
DropDown.closeFrame(records);

则在主界面CustomDropDown的onSelect函数中就可以获得closeFrome()返回的自定义信息,查看onSelect函数的申明:

Public Boolean onSelect(DropDown dropdown, Object selectedObject, TextEditor editor)

其中第二个参数就是DropDown.closeFrame()方法返回的对象。范例如下:

Public Boolean onSelect(DropDown dropdown, Object selectedObject, TextEditor editor){
var text = "";
var records = selectedObject;
for (var i = 0; i < records.length; i++) {
var record = records[i];
if (i > 0) text += ",";
text += record.getValue("degree");
}
datasetEmployee.setValue("degree", text);
return false;
}

onSelect详细说明参考API文档

常用技巧

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

自定义下拉框还会存在一些复杂的用法

如用户希望返回的是一组record,在doradosample中有一个范例:

图表 10
控件体验/录入辅助 页面上的"其它"编辑框对象,可以实现多选下拉功能。由于该种应用中返回的数据不再是简单的record对象,因此我们在sample/control/InputAssist.view.xml文件中dropdownEmployeeMultiSel1的配置属性里并没有设定readFields,writerFields属性,下拉框页面的视图模型中sample/control/DropdownEmployeeMultiSel.view.xml中的按钮buttonOK的onClick事件中的代码如下:

Var records = new Array();
var record = datasetEmployee.getFirstRecord();
while (record != null) {
if (record.getValue("select")) {
records.push(record);
}
record = record.getNextRecord();
}
DropDown.closeFrame(records);

通过DropDown.closeFrame(records)返回一组record对象。而主页面则是通过dropdownEmployeeMultiSel1的onSelect事件负责接受这一组record

Var records = selectedObject;//被引用页面通过DropDown.closeFrame(records)放回的records对象
datasetEmployee.disableControls();
for (var i = 0; i < records.length; i++) {
var record = records[i];
datasetEmployee.insertRecord();
datasetEmployee.copyRecord(record);
datasetEmployee.postRecord();
}
datasetEmployee.enableControls();
datasetEmployee.refreshControls();

editor.setValue("选择了" + records.length + "位员工!");
return false;

以上的例子都是基于record返回数据的,实际上DropDown.closeFrame()方法返回的信息可以支持任何一种对象,如字符串,或用户自定义的Object对象

通过按钮打开CustomDropDown,通过选择直接新增记录

按钮的onClick事件:

Var subwinDD = peopleDropDown;
subwinDD.open();

CustomDropDown的onSelect事件代码如下:

onSelect(DropDown dropdown, Object selectedObject, TextEditor editor){
var ds = dsPeople;
var r = ds.getCurrent();
if(!r){ds.insertRecord() ; r = ds.getCurrent(); }
r.setValue("id", selectedObject.getValue("id"));
r.setValue("name", selectedObject.getValue("name"));

return false;
}

动态编程

在服务器段动态生成CustomDropDown

protected void initControls() throws Exception {
super.initControls();//系统默认函数,注意保留
CustomDropDown dropdown1= (CustomDropDown)createControl("CustomDropDown","dropdown1");
dropdown1.setPath("dropdown-employee-tree.jsp ");//关联被引用的JSP页面
dropdown1.setFixed(true);
dropdown1.setReadFields("employee_id,employee_name");
dropdown1.setWriteFields("field1,field2");
}

使用视图模型实现类提供的createControl方法创建CustomDropDown对象,注意第一个参数用以指定组件的类型,第二个参数指定新建对象的id

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

protected void initControls() throws Exception {
super.initControls();//系统默认函数,注意保留
CustomDropDown dropdown1= (CustomDropDown)getControl("dropdown1");
dropdown1.setPath("dropdown-employee-tree.jsp ");//关联被引用的JSP页面
dropdown1.setFixed(true);
dropdown1.setReadFields("employee_id,employee_name");
dropdown1.setWriteFields("field1,field2");
}

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

主要属性说明

参考ListDropDown的主要属性说明
参考DatasetDropDown的主要属性说明
参考DynamicDropDown的主要属性说明

属性

说明

path

被引用的下拉框页面的url

readFields

下拉选择后系统自动从下拉框绑定的页面中要读取值的字段名,多个字段用逗号","隔开,该属性与writeFields配合使用,用于实现多个字段同时赋值的功能
该属性只有在下拉框界面返回的对象是record时才起作用,否则需要用户自行定义下拉框的onSelect事件实现具体的逻辑

writeFields

与readFields配合使用,用于指定下拉选择后系统自动从下拉框页面中读取readFields中指定字段的值,并写入绑定下拉框的编辑框所绑定的dataset中writeFields指定的字段中去
该属性只有在下拉框界面返回的对象是record时才起作用,否则需要用户自行定义下拉框的onSelect事件实现具体的逻辑

主要事件说明

基本事件参考ListDropDown的主要事件说明

事件

说明

Public Boolean onSelect(DropDown dropdown, Object selectedObject, TextEditor editor)

当选择了下拉数据时触发
此事件的返回值用于通知系统是否要继续完成后续的为编辑框或数据集赋值的操作.返回true表示继续默认的赋值操作.
参数说明:
dropdown - 触发事件的下拉框对象
selected
Object - 下拉框框页面中通过DropDown.closeFrame(object)方法关闭时传递回的object参数对象
editor -打开此下拉框的编辑框对象

如返回的数据是一个record,并且所需要执行的逻辑是可以通过readFields,writeFields属性定义的时候,我们就不需要再来定义onSelect事件

CSS说明

由下拉框对应的JSP定义