3

我对 ADF Faces 表和动态区域有疑问。

前提条件:
Oracle JDeveloper 11.1.1.6.0

我正在使用 ADF Faces 和 ADF 绑定层在 af:table 中显示 Java POJO 列表。ADF 表显示在有界任务流内的视图上。
此任务流用于另一个视图上的动态区域。
导航包含两个链接,用于通过 bean-property 选择要在动态区域中显示的有界任务流。
动态区域通过任务流绑定接收“输入参数映射”。
此映射包含要在表中显示的 POJO 和一个 state-Bean,它应该保存表状态和视图上可能的其他组件的状态(请参见下面的实现)。

问题/要求:

1.预选:

首次加载表时,根据 POJO 中包含的数据预选表中的单行。

2.继续选择任务流开关:

在切换到另一个有界任务流 B 并返回 A(表所在的位置)后,也应该选择表中的选定行(有界任务流 A)。

3.没有MDS

不使用保存点/MDS 功能。

4.一致的表模型和绑定层

在任务流之间切换和选择表格中的元素之后,应该可以询问表格组件和所选行的绑定。
切换任务流和选择表中元素后,绑定中的表行和选中行应保持一致。

已经尝试过:

在不使用 MDS/保存点的情况下预选一行并继续选择任务流切换。

我已经将一些表属性绑定到“状态”bean。bean 的实现附在下面。

1.表格的属性:

选定的行键:
selectedRowKeys="#{pageFlowScope.stateBean.tableStateBean.rowKeySet}"

绑定 RichTable 的 Backing-Bean 属性:
binding="#{pageFlowScope.stateBean.tableStateBean.richTable}"

默认选择监听器
selectionListener="#{bindings.postanschriften.collectionModel.makeCurrent}"

我们在这里尝试的是:
在表的初始加载和更改行 bean 方法时调用 getRowKeySet(..)。
在此方法中,要选择的行是在初始表加载时计算的(this.rowKeySet == null)。因为 table 属性 selectedRowKeys 绑定到pageFlowScope.stateBean.tableStateBean.rowKeySetbean 中的属性,如果在 table 中选择了另一行,则会更新。如果我们将任务流从 A 更改为 B,反之亦然,则调用支持 bean 属性richTable 的 getter。在 getter 方法中,选择状态被恢复。

2.“状态”bean的实现:

public class TableStateBean {
    private RichTable richTable;
    private RowKeySet rowKeySet;
    private String bindingIteratorName;
    private RowMatcher matcher;

public RowKeySet getRowKeySet() {
    if (this.rowKeySet == null) {
        preselectRow();
    }
    return rowKeySet;
}

public RichTable getRichTable() {
    if (richTable != null && rowKeySet != null) { 
        RowKeySet currentTableSelection = getCurrentTableSelection();
        RowKeySet tableSelectionToRestore = getTableSelectionToRestore();
        executeSelection(tableSelectionToRestore, currentTableSelection);
    }
    return richTable;
}

public void setRichTable(RichTable pRichTable) {
    richTable = pRichTable;
}

public void doTableSelection(){
    preselectRow();
}


private RowKeySet getCurrentTableSelection() {
    Row currentRow = (Row) JSFUtils.resolveExpression("#{bindings." + this.bindingIteratorName + ".currentRow}");
    Key currKey = currentRow.getKey();
    ArrayList<Key> lst = new ArrayList<Key>(1);
    lst.add(currKey);
    RowKeySet keySet = new RowKeySetImpl();
    keySet.add(lst);
    return keySet;
}

private RowKeySet getTableSelectionToRestore() {
    RowKeySet tableSelectionToRestoreRow = null;
    RowSetIterator rowSetIterator = extractRowSetIterator();
    int tableRowIndexOfCurrentSelectedKey = getSingleRowKeyIndexValue(this.rowKeySet);

    if (tableRowIndexOfCurrentSelectedKey != -1) {
        Row currentRow = rowSetIterator.first();
        for (int i = 0; rowSetIterator.hasNext() && i < tableRowIndexOfCurrentSelectedKey; i++) {
            currentRow = rowSetIterator.next();
        }
        if (currentRow != null) {
            Key newSelectionKey = currentRow.getKey();

            ArrayList<Key> keyList = new ArrayList<Key>(1);
            keyList.add(newSelectionKey);

            tableSelectionToRestoreRow = new RowKeySetImpl();
            tableSelectionToRestoreRow.add(keyList);
        }
    }

    return tableSelectionToRestoreRow;
}

private int getSingleRowKeyIndexValue(RowKeySet rowKeySet) {
    int tableRowIndexOfCurrentSelectedKey = -1;

    if (rowKeySet != null) {
        Object[] rowKeySetArray = rowKeySet.toArray();
        List<Key> selectedRowKeys = (rowKeySetArray.length > 0) ? (List<Key>) rowKeySetArray[0] : new ArrayList<Key>();
        if (selectedRowKeys.size() > 0) {
            Key currentSelectedKey = selectedRowKeys.get(0);
            Object[] attributeValues = currentSelectedKey.getAttributeValues();
            assert (attributeValues.length > 0);
            tableRowIndexOfCurrentSelectedKey = (Integer) attributeValues[0];
        }
    }
    return tableRowIndexOfCurrentSelectedKey;
}

private void executeSelection(RowKeySet newCurrentRow, RowKeySet oldCurrentRow) {
    SelectionEvent selectionEvent = new SelectionEvent(oldCurrentRow, newCurrentRow, richTable);
    selectionEvent.queue();
    AdfFacesContext.getCurrentInstance().addPartialTarget(richTable);
}

protected void preselectRow() {
    RowSetIterator rowSetIterator = extractRowSetIterator();

    RowKeySet oldSelection = getCurrentTableSelection();        
    Row currentRow = rowSetIterator.first();
    while (rowSetIterator.hasNext() 
           && (!matcher.match(currentRow))) // Matcher selects which row should be displayed according to the Object bound behind the binding-layer.
    {
        currentRow = rowSetIterator.next();
    }
    if (currentRow != null) {

        Key key = currentRow.getKey();
        RowKeySet newSelection = createRowKeySet(key);            
        setActiveRowKey(key);
        executeSelection(newSelection, oldSelection);
        setRowKeySet(newSelection);
    }
}

private void setActiveRowKey(Key pKey) {
    ArrayList<Key> lst = new ArrayList<Key>(1);
    lst.add(pKey);
    this.richTable.setActiveRowKey(lst);
}

private RowKeySet createRowKeySet(Key pKey) {
    ArrayList<Key> lst = new ArrayList<Key>(1);
    lst.add(pKey);
    RowKeySetImpl rowKeySetToCreate = new RowKeySetImpl();
    rowKeySetToCreate.add(lst);
    return rowKeySetToCreate;
}

private RowSetIterator extractRowSetIterator() {
    DCIteratorBinding iteratorBinding = ADFUtils.findIterator(this.bindingIteratorName);
    RowSetIterator rowSetIterator = iteratorBinding.getRowSetIterator();
    return rowSetIterator;
    }
}

在某些情况下,绑定层似乎与在 RichTable 组件上选择的元素不同步。所以我猜上面提到的解决方案不是很健壮。

是否有另一种方法可以以稳健的方式归档上述功能?我认为根据绑定的POJO中的一些值来预选表中的一行并不是那么奇怪。并且在有界任务流(动态区域)之间切换后保持表格的选定行应该是可能的,不是吗?

感谢您期待您的帮助

问候,

最大限度

4

2 回答 2

0

设置“选定”行相当容易。有几种解决方案。这只是其中之一:为您的表绑定到您的支持 bean。在 getter 中添加以下代码:

DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding dcItteratorBindings =
bindings.findIteratorBinding("yourViewObjectIterator");
RowSetIterator it = dcItteratorBindings.getRowSetIterator();
Rows[] rows = voTableData.getAllRowsInRange();
Row needsSelection = null;
for(Row r: rows)
{
   //just search for the row you want to set selected
  if(r.getAttribute("SomeAttribute").eqauls(..))
     needsSelection = r;
}

if(needsSelection != null)
it.setCurrentRow(needsSelection);
于 2012-11-20T11:20:12.613 回答
0

您可能想要查看您的应用程序设计。使用单个任务流在两个视图活动(页面片段)之间导航可能是更简单的解决方案,而不是使用动态区域并在两个任务流之间切换。此外,您编写了大量代码只是为了保持行选择。您只需要存储所选行的唯一列的数据,并使用上述帖子中使用 DCBinding 迭代器提供的逻辑将行选择设置为该行。

于 2013-03-09T05:42:22.543 回答