转自http://www.yonaweb.be/creating_your_own_treemodel_adf_11g_0
published by Yannick on 22 February, 2011 - 08:20
Building your own tree in ADF does not seem that easy at first sight but in fact it is not that hard if you know what to do. On the forum at OTN you often find questions about building your own model.
In this post you will find the steps needed to build your own model. In the example i just use some static data but you can rewrite it to use whatever you want.
We will build a tree that has 2 nodes in the root and the first node has 2 children.
Our TreeModel contains objects of the type TreeItem. TreeItem is not a build in class. I call it TreeItem but you can name it whatever you want. It is a regular bean with getters and setters. In order to build a tree, the class should have a method that returns its children.
This is the TreeItem class we will be using:
public class TreeItem { private String text,action; private List<TreeItem> children; public TreeItem() { super(); } public TreeItem(String text,String action){ super(); this.text = text; this.action = action; } public void setText(String text) { this.text = text; } public String getText() { return text; } public void setAction(String action) { this.action = action; } public String getAction() { return action; } public void setChildren(List<TreeItem> children) { this.children = children; } public List<TreeItem> getChildren() { return children; } }
As you can see, the TreeItem has 3 properties:
You are free to add more properties. Every property you add to the TreeItem you can use it in the tree itself.
Next we need to create our managed bean. This will contain the TreeModel itself.
In fact we just create the rootNode and use a default TreeModel from ADF. This is the ChildPropertyTreeModel.
We will build the tree in the constructor of the bean:
public TreeExample() { root = new ArrayList<TreeItem>(); TreeItem node1 = new TreeItem("Node1","node1"); TreeItem node2 = new TreeItem("Node2","node2"); root.add(node1); root.add(node2); ArrayList<TreeItem> node1Children = new ArrayList<TreeItem>(); TreeItem node1Child1 = new TreeItem("Child 1","child1"); TreeItem node1Child2 = new TreeItem("Child 2","child2"); node1Children.add(node1Child1); node1Children.add(node1Child2); node1.setChildren(node1Children); setListInstance(root); } public void setListInstance(List instance) { this.instance = instance; model = null; }
The af:tree component requires a TreeModel as value so we need to create such a property as well:
public TreeModel getModel() { if(model == null) model = new ChildPropertyTreeModel(instance,"children"); return model; }In this methode we will create the actual TreeModel based upon the root we created in the constructor. As you can see we also need to specify the name of the method that will return the children. By specifying "children" as a second parameter of the ChildPropertyTreeModel constructor, we tell the framework to call getChildren() in order to retreive the list of children.
When this is done, we need to register the bean to the faces-config.xml:
<managed-bean> <managed-bean-name>TreeExample</managed-bean-name> <managed-bean-class>view.beans.TreeExample</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
As a final step we need to add the tree to the page:
<af:tree value="#{TreeExample.model}" var="node"> <f:facet name="nodeStamp"> <af:commandLink text="#{node.text}" action="#{node.action}"/> </f:facet> </af:tree>
另附一篇文章:
http://one-size-doesnt-fit-all.blogspot.com/2007/05/back-to-programming-programmatic-adf.html
Typically ADF Faces components in our JDeveloper 10.1.3 applications are data bound, meaning they map to objects in the binding layer as specified in separate pageDef files. This is expressed in our components through EL references to bindings}.
However what if we don't want to map to a binding layer object, but instead want to construct the data elements programmatically? For this blog we'll consider the example of an <af:tree> component to demonstrate this, showing how we construct the elements in the tree programmatically rather than relying on bindings.
Our goal is to construct an <af:tree> component comprised of <af:goLink> tags and looks as follows:
Logically understanding our hierarchy
Before we consider the <af:tree> component specifically, have a think about what the hierarchy represents. Each node in the tree has a text title, and a hyperlink destination. Each node is a child to a parent node, and each node may be comprised of 0, 1 or more child nodes. Collectively this represents our tree and is a simple logical concept.
Understanding the ADF Faces Tree component
The code for an <af:tree> in a web page would typically look as follows:
<af:tree var="node" value="#{treeModel.model}">
<f:facet name="nodeStamp">
<af:goLink text="#{node.text}" destination="#{node.destination}"/>
</f:facet>
</af:tree>
In our example you'll note that the nodes within the tree are comprised of <af:goLink> tags that render the links in our tree above. You'll also note if you constructed a <af:tree> tag using the drag n drop facilities of JDeveloper based on a data bound component from the data control palette, the code would look very similar. In other words there isn't anything really special about the code above besides the use of <af:goLink> tags.
The <af:tree value> attribute demands at runtime an oracle.adf.view.faces.model.TreeModel instance. This class is the data model for the ADF Faces Tree component, where rows in the tree may contain other trees, or alternatively described, nodes in the tree can contain children nodes which in turn can also have children nodes and so on.
The nodeStamp facet of the <af:tree> walks the TreeModel, creating for each node the subtags contained within the <f:facet> tag, in this case an <af:goLink> tag. You'll note the <af:goLink> tag makes reference to the current node in the TreeModel as it walks the tree via the <af:tree> tag's var="node" attribute.
So we now logically have an understanding of what we want to model, and we also understand what the <af:tree> component wants. Lets consider our design solution.
Keeping it simple with a POJO
From the design point of view, to model the hierarchy we'd like to create our own very simple POJO TreeItem that stores a String text and String destination required for each goLink, along with a List of children TreeItem objects to reflect the hierarchy. At runtime we'll construct this tree programmatically populating the hierarchy in any way we desire.
The POJO approach is very easy to understand and implement. However the problem with our POJO approach is the datatype doesn't match that required by the <af:tree>, namely oracle.adf.view.faces.model.TreeModel. How do we address this?
Creating an Adapter between our TreeItem and TreeModel
In the OO world they have the concept of the adapter design pattern. An Adapter class is one that wraps another interface, to provide an interface the client expects. In our case we have our POJO TreeItem interface, but our client the <af:tree> demands an oracle.adf.view.faces.model.TreeModel, so we'll provide a class called TreeModelAdapter to work as the adapter. It will be this class that we'll define in our faces-config.xml file as a managed bean for the <af:tree> control to make use of at runtime.
The TreeModelAdapter will internally store our TreeItem hierarchy and TreeModel, and provide accessor methods to access and manipulate these items.
Coding the solution
The following describes the steps in coding our design solution. It assumes you've already created your web page with the <af:tree> code as previous:
Create our POJO Java Bean TreeItem class as follows:
package view;
import java.util.List;
public class TreeItem {
private String _text = null;
private String _destination = null;
private List<treeitem> _children = null;
public TreeItem(String text, String destination) {
setText(text);
setDestination(destination);
}
public String getText() { return _text; }
public void setText(String text) { this._text = text; }
public String getDestination() { return _destination; }
public void setDestination(String destination) { this._destination = destination; }
public List getChildren() { return _children; }
public void setChildren(List children) { this._children = children; }
}
Note the following about the TreeItem class: