Tuesday, February 23, 2010

Flex Custom Datagrid for Hierarchical data




Step 1: Create a sample hierarchical dataprovider with category, author and title field.

<mx:ArrayCollection id="bookCollection">

<mx:Object Category="java">

<mx:data>

<mx:Object Author="sam" Title="java patterns" />

<mx:Object Author="dennis" Title="java architecture" />

<mx:Object Author="jack" Title="java swing" />

</mx:data>

</mx:Object>

<mx:Object Category="Mainframe">

<mx:data>

<mx:Object Author="dennis" Title="mainframe architecture" />

<mx:Object Author="jack" Title="mainframe basics" />

</mx:data>

</mx:Object>

</mx:ArrayCollection>


Step 2: Create AdvancedDatagrid control with dataprovider created in step 1

Specify the datagrid attributes width, height, dataprovider, variableRowHeight.

<mx:AdvancedDataGrid width="100%" height="100%" dataProvider="{bookCollection}" variableRowHeight="true">

Define three columns col1, col2 and col3 and a renderer for col2.

For col1 definition define an extra attribute datafield when compared to the other columns.

<mx:AdvancedDataGridColumn id="col1" dataField="Category" headerText="Category"/>

I have defined one renderer specifying the attributes column, columnSpan, renderer.

<mx:rendererProviders>

<mx:AdvancedDataGridRendererProvider column="{col2}" columnSpan="2" renderer="DatagridRenderer" />

</mx:rendererProviders>



CustomGridApp.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%">

<mx:ArrayCollection id="bookCollection">

<mx:Object Category="java">

<mx:data>

<mx:Object Author="sam" Title="java patterns" />

<mx:Object Author="dennis" Title="java architecture" />

<mx:Object Author="jack" Title="java swing" />

</mx:data>

</mx:Object>

<mx:Object Category="Mainframe">

<mx:data>

<mx:Object Author="dennis" Title="mainframe architecture" />

<mx:Object Author="jack" Title="mainframe basics" />

</mx:data>

</mx:Object>

</mx:ArrayCollection>

<mx:AdvancedDataGrid width="100%" height="100%" dataProvider="{bookCollection}" variableRowHeight="true">

<mx:columns>

<mx:AdvancedDataGridColumn id="col1" dataField="Category" headerText="Category"/>

<mx:AdvancedDataGridColumn id="col2" headerText="Author"/>

<mx:AdvancedDataGridColumn id="col3" headerText="Title"/>

</mx:columns>

<mx:rendererProviders>

<mx:AdvancedDataGridRendererProvider column="{col2}" columnSpan="2" renderer="DatagridRenderer" />

</mx:rendererProviders>

</mx:AdvancedDataGrid>

</mx:Application>

Step 3: Create custom component extending advanceddatagrid

DatagridRenderer.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:AdvancedDataGrid xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" showHeaders="false" >

<mx:Script>

<![CDATA[

import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;

private var columnArray:Array = new Array();

public override function set data(value:Object):void

{

super.data = value;

var column:AdvancedDataGridColumn = null;

if(value.data.length > 0)

{

//Set the dataprovider

this.dataProvider = value.data;

//Create the columns needed and

//add labelfunction to the columns

column = new AdvancedDataGridColumn();

column.headerText = "Author";

column.labelFunction = datagridLabelFunction;

columnArray.push(column);

column = new AdvancedDataGridColumn();

column.headerText = "Title";

column.labelFunction = datagridLabelFunction;

columnArray.push(column);

setColumns();

}

}

private function setColumns():void

{

var col:Array = this.columns;

//Remove the columns defined earlier

while(col.length > 0)

{

col.shift();

}

//Add the custom defined columns

while(columnArray.length > 0)

{

col.push(columnArray.shift());

}

this.columns = col;

}

private function datagridLabelFunction(item:Object, col:AdvancedDataGridColumn):String

{

var label:String = null;

label = item[col.headerText];

return label;

}

]]>

</mx:Script>

</mx:AdvancedDataGrid>