Skip to main content

Custom ItemRenderer for Tree Control in Flex

In this post I am going to describe how you can modify the appearance of tree control. There are some examples already available on the internet but still I had to do some research and work to get this thing done. I am going to follow a Top-Down approach so you can follow along easily.


Step-1 Making a Tree Control:

We need an xml to provide it as a data provider to a tree control.

A sample XML for the tree:


<mx:xmllist id="treeData">
<node label="Root">
<node label="Parent-1">
<node label="Child-1">
<node label="Child-2">
<node label="Child-3">
<node label="Child-4">
</node>
<node label="Parent-2">
</node>
</mx:XMLList>

MXML for the tree:

<mx:tree id="myTree" labelfield="@label"

labelfield="@label"
showRoot="false"
dataProvider="{treeData}"
change="treeChanged(event)"
itemRenderer="MyRenderers.MyTreeItemRenderer" />



LabelField: Dictates which node attribute from the “node” will be used to display each tree node value. In the sample xml the tree will look like this.

showRoot: As the name suggests it determines whether the root element is shown or not.

dataProvider: Flex assigns whatever is provided here to the tree as input data.

Change: This is an event handler which will be covered later on.

itemRenderer: This is where the Magic happens you assign this property of the tree to something which can be used to override the default behavior of the tree. In this case

MyRenderers.MyTreeItemRenderer refers to an .as file which serves as the itemrenderer.



Step-2 Making an ItemRenderer:

Your itemrenderer will be inherited from the built-in flex control, which you want to modify in our case it will be a tree control. So your class definition will look like this

public class MyTreeItemRenderer extends TreeItemRenderer

There are two important functions to override which will modify the default tree control. In our example we will be adding an image to the leaf nodes and the tree will look like this.


In addition to the default behavior of the tree we have added an image with the child nodes. To achieve this functionality we have to override two functions in the derived class.

Overiding createChildren()

override protected function createChildren():void

{

super.createChildren();

customItem=new Image();

customItem.source = 'Images/helpIcon.jpg';

customItem.addEventListener(MouseEvent.CLICK,helpEvent,true);

this.addChild(customItem);

}

Here as you can see we have instantiated an image control, assigned its source, added an event listener in case you want to add some kind of event handling to the control you are adding and finally added the instantiated control to the tree control. This function is called for each and every node in the xml which is given in the dataProvider property of the tree so each and every node has an image attached to it.


Overiding updateDisplayList()

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void

{

var treeListData:TreeListData=TreeListData(listData);

super.updateDisplayList(unscaledWidth,unscaledHeight);

if(treeListData.hasChildren)

{

this.setStyle("fontWeight","bold");

this.label.text = this.label.text.toUpperCase();

customItem.visible=false;

}

else

{

this.setStyle("fontWeight","normal");

icon.visible=true;

customItem.width=20;

customItem.height=20;

customItem.x=label.textWidth+label.x+5;

}

}

This function is responsible to display the tree control, the treeListData contains the xml data passed to the tree control. Now we are interested in displaying the image we added in the createChildren() to each node. We only want to display the image only if the node is a leaf node(you can do otherwise as well) but sticking to the example we do this check:

if(treeListData.hasChildren)

that means that the node is not a leaf node and we hide the customItem(image in our case) by doing

customItem.visible=false;


The else part handles the leaf nodes and we configure how the leaf nodes and the image shall be displayed.


That’s it you have made your CustomItemRenderer!!

Here is the complete code for the class.

package MyRenderers {

import flash.events.Event;

import flash.events.MouseEvent;

import mx.collections.*;

import mx.controls.Image;

import mx.controls.treeClasses.*;

public class MyTreeItemRenderer extends TreeItemRenderer {

private var customItem:Image;

public function MyTreeItemRenderer()

{

super();

}

private function helpEvent(event:Event):void

{

var e:FormatHelpEvent = new FormatHelpEvent("formatHelp");

dispatchEvent(e);

}

override protected function createChildren():void

{

super.createChildren();

customItem=new Image();

customItem.source = 'Images/helpIcon.jpg';

customItem.addEventListener(MouseEvent.CLICK,helpEvent,true);

this.addChild(customItem);

}

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void

{

var treeListData:TreeListData=TreeListData(listData);

super.updateDisplayList(unscaledWidth,unscaledHeight);

if(treeListData.hasChildren)

{

this.setStyle("fontWeight","bold");

this.label.text = this.label.text.toUpperCase();

customItem.visible=false;

}

else{

this.setStyle("fontWeight","normal");

icon.visible=true;

customItem.width=20;

customItem.height=20;

customItem.x=label.textWidth+label.x+5;

}

}

}

}


Comments

Unknown said…
How are you then separating the click functions if on the help icon or over the node of tree? I have implemented your brilliant snippet but when i click on icon it triggers both method calls.
Arslan said…
Hello MOI, thanks for your input. Your question is very valid and requires a detail explanation so i explained it in another article i really hope this helps you. please visit http://pudgylogic.blogspot.com/2009/09/custom-events-from-custom-item-renderer.html
Do ask me if anything comes up in your mind.
Unknown said…
mate, you rule

i tried the standard mxml component, but never in the life of me have thought about replicating the treeitemrenderer function.

and to think all i wanted was bold on the selected item
Hi Arslan,

Thanks a lot. That was a hell lot of help for me. I was trying to build an organizational chart by modifying the tree. Hope this will help me to reach my goal. And if you have any idea on how this can be accomplished, please share the same.
Arrowz said…
how to change the image's source dynamically for a particular node when some data is changed - Thanks - KS