ADF 11g Multiple RowSelect on RichTable

在实际应用中,经常遇到需要在表格中选定一条或多条记录进行操作的情况。

下面将详述三种实现方式,使用Oracle JDeveloper 11.1.1.0.1,数据源使用OracleXE版本中HR示例数据的Employees表,创建页面时默认绑定backingbean。
1.使用ADF RichTable提供的Multiple RowSelect
优点:RichTable原生支持,稳定快速,代码简单 缺点:只能按住键盘Ctrl键或Shift键通过鼠标进行多选,用户操作不直观 步骤:设置RichTable的属性,将RowSelection设为multiple,并将SelectedRowKeys设为空,即可在后台通过如下代码获得选定行的RowKey,进而可以通过在VO上通过对应RowKey得到对应行。
    public Boolean getIsChecked() {
//return (Boolean) getAttributeInternal(ISCHECKED);
return getAttributeInternal(ISCHECKED) == null ? false :
(Boolean)getAttributeInternal(ISCHECKED);
}
补充:为什么将SelectedRowKeys置为空 修改之前SelectedRowKeys值为#{bindings.EmployeesVO1.collectionModel.selectedRow},该EL表达式表明之前该Table的SelectedRowKeys绑定到了对应VO的selectedRow,但client端的状态改变并不能实时的提交到Server端,以至于当此绑定存在时,取到的是Server端存储的selectedRow而非client端当前的selectedrow。 2.在RichTable中增加列,使用基于VO的Checkbox进行RichTable的行多选 优点:使用checkbox的方式提供选择,代码复杂度中等 缺点:必须修改每一个需要使用该多选方式的RichTable对应的VO 步骤:

1. 在VO添加非数据库项IsChecked,设置其Type为Boolean,Updateable为Always
  • 为该VO生成ViewRowImpl.java,并修改IsChecked的get方法
        public Boolean getIsChecked() {
    //return (Boolean) getAttributeInternal(ISCHECKED);
    return getAttributeInternal(ISCHECKED) == null ? false :
    (Boolean)getAttributeInternal(ISCHECKED);
    }

  • 将VO拖入页面创建RichTable,修改IsChecked列,将标签改为<af:selectBooleanCheckbox>,并将其Autosubmit/Immediate属性设为true,并在header中拖入另一个SelectBooleanCheckbox
  • header里的Checkbox不能添加ValueChangeListener,如果已经添加,需要将ValueChangeListener重置为Default(空)。为Header里的Checkbox创建ClientListener和ServerListener,分别设置属性如下: ClientListener method: mainClientCall type: click
    ServerListener method: callMBmainmethod type: onSelectedOrDeselected()
    完成后如下


  • 在页面转入Source模式,在标签 <af:document… <af:messages… 间加入如下代码
          <script type="text/javascript">
    <![CDATA[function mainClientCall (event)
    {
    var currcheckbox = event.getSource();
    var selectstatus = currcheckbox.getValue();
    //call method in manage bean
    AdfCustomEvent.queue(currcheckbox, "callMBmainmethod",{params:selectstatus}, true);
    }
    ]]>
    </script>

  • 在页面backingbean中修改onSelectedOrDeselected方法,添加以下代码以实现全选功能。注意修改this.getTable()为你的目标表。
        public void onSelectedOrDeselected(ClientEvent clientEvent) {
    boolean isSelected =
    (Boolean)clientEvent.getParameters().get("params");
    RichTable rt = this.getTable1();
    for (int i = 0; i < rt.getRowCount(); i++) {
    JUCtrlHierNodeBinding rowData =
    (JUCtrlHierNodeBinding)rt.getRowData(i);
    Row row = rowData.getRow();
    if (isSelected) {
    row.setAttribute("IsChecked", true);
    } else {
    row.setAttribute("IsChecked", false);
    }
    }
    // Refresh target table state
    AdfFacesContext adfContext = AdfFacesContext.getCurrentInstance();
    UIComponent refreshComponent = this.getTable1();
    if (refreshComponent != null) {
    adfContext.addPartialTarget(refreshComponent);
    }
    }

  • 可以在AppModel或ManageBean中通过遍历VO判断IsChecked的状态来取出选定行。 3.在RichTable中增加列,不基于VO进行RichTable的行多选 优点:使用checkbox的方式提供选择,不必修改VO 缺点:代码复杂度较高

    1. RichTable中插入列,设置宽度(width)为13RowHeader属性为trueAlign属性为Center;在列及列header中分别拖入SelectBooleanCheckBox,设置checkboxsimple属性为true,删除其Text属性中的值。将全选checkboxID设置为maincheckbox,单选的checkbox ID设置为subcheckbox:(参考2.3)
  • 分别为两个Checkbox创建一组ClientListener/ServerListener,属性设置如下(参考2.4) MainCheckbox clientListener Method: mainClientCall Type: click serverListener Type: callMBmainmethod Method: mainCheckBoxChecked() SubCheckbox clientListener Method: subClientCall Type: click serverListener Type: callMBsubmethod Method: subCheckBoxChecked()
  • 在页面转入source模式,复制如下代码至<af: document …<af: messages …标签之间(参考2.5)
          <script type="text/javascript">
    <![CDATA[function mainClientCall (event)
    {
    var currcheckbox = event.getSource();
    var selectstatus = currcheckbox.getValue();
    //call method in manage bean
    AdfCustomEvent.queue(currcheckbox, "callMBmainmethod",{params:selectstatus}, true);
    }
    function subClientCall (event)
    {
    var currcheckbox = event.getSource();
    var selectstatus = currcheckbox.getValue();
    //call method in manage bean
    AdfCustomEvent.queue(currcheckbox, "callMBsubmethod",{params:selectstatus}, true);
    }
    ]]>
    </script>

  • 修改页面对应Manage bean中的方法,修改mainCheckBoxChecked()subCheckBoxChecked()方法,添加如下代码
        public void getSelectedRows(ActionEvent actionEvent) {
    System.out.println("Selected Rows"); //debug
    System.out.println("**"); //debug
    RowKeySet selectedRowsList = this.getMultipleCheckBoxProcess().getSelectedRowsList(this.getResId1());
    if (selectedRowsList != null && selectedRowsList.size() != 0) {
    for (Object temp : selectedRowsList)
    System.out.println("Get Row : " + temp);
    }
    System.out.println("**"); //debug
    }
    public void CleanUpStatus(ActionEvent actionEvent) {
    this.getMultipleCheckBoxProcess().CleanUpStatus(this.getResId1(), "maincheckbox", "subcheckbox");
    }
    public void mainCheckBoxChecked(ClientEvent clientEvent) {
    Boolean currstatus = (Boolean)clientEvent.getParameters().get("params");
    this.getMultipleCheckBoxProcess().mainCheckBoxChecked(this.getResId1(), "subcheckbox", currstatus);
    }
    public void subCheckBoxChecked(ClientEvent clientEvent) { Boolean currstatus = (Boolean)clientEvent.getParameters().get("params");
    this.getMultipleCheckBoxProcess().subCheckBoxChecked(this.getResId1(), currstatus);
    }
    public MultipleCheckBox getMultipleCheckBoxProcess(){
    FacesContext ctx = FacesContext.getCurrentInstance();
    Application app = ctx.getApplication();
    MultipleCheckBox curr = (MultipleCheckBox)app.evaluateExpressionGet(ctx, "#{ viewScope.view_MultipleCheckbox}", Object.class);
    return curr;
    }

  • 复制MultipleCheckbox.java至目标位置(在Demo中可以找到),在当前所使用的TaskFlow中添加Manage Bean名为view_MultipleCheckbox,Scope为view级别的Bean,指向MultipleCheckbox.java,修改MultipleCheckbox.java中的Package,使其与实际路径相符。
  • 注意在适当的时候调用MultipleCheckbox的CleanUpStatus方法,一般在RichTable中数据发生改变时需要调用,如页面存在Query,则需在Query中调用MultipleCheckbox的CleanUpStatus方法。
  • 补充:MultipleCheckBox中方法说明

    * public RowKeySet getSelectedRowsList(RichTable tartab); 输入参数1:使用多选择CheckboxRichTable对象 返回参数:选中的行的RowKey
  • public void setSelectedRowsList(RowKeySet selectedRowsList, RichTable tartab); 输入参数1:选中行的RowKey 输入参数2:使用多选择CheckboxRichTable对象
  • public void subCheckBoxChecked(RichTable tartab, Boolean checkStatus); 输入参数1:使用多选择CheckboxRichTable对象 输入参数2:当前Checkbox的状态 该方法应在多Checkbox RichTable中某行前的Checkbox被选中/反选时调用
  • public void mainCheckBoxChecked(RichTable tartab, String subcheckboxid, Boolean newstatus); 输入参数1:使用多选择CheckboxRichTable对象 输入参数2:每行前Checkboxid 输入参数3:当前全选Checkbox的状态 该方法应在全选Checkbox被选中/反选时调用
  • public void CleanUpStatus(RichTable tartab, String maincheckboxid, String subcheckboxid); 输入参数1:使用多选择CheckboxRichTable对象 输入参数2:全选Checkboxid 输入参数3:每行前Checkboxid 该方法用于清除Checkbox的被选状态,通常需要执行查询前均需调用Demo: http://cid-0ee24905211c3ffd.skydrive.live.com/embedrow.aspx/Public/Hand/ADF/MultipleRowSelect1.rar
    http://cid-0ee24905211c3ffd.skydrive.live.com/embedrow.aspx/Public/Hand/ADF/MultipleRowSelect2.rar
    http://cid-0ee24905211c3ffd.skydrive.live.com/embedrow.aspx/Public/Hand/ADF/MultipleRowSelect3.rar