Tuesday, 20 November 2007

How to color Datagrid cells/rows in flex 2

I have been looking for a easy and neat way to color a single cell or a complete row in flex 2.

Google brought me two interesting links:

1. How opaqueBackground can be used to color the background of a label itemRenderer
The comment posted by Dallas at 11/10/06 8:01, shows a way of highlighting a cell. Very simple implementation - the only problem is that the background color won't react on mouseover after the opaqueBackground is set.

2. How do you change the background cell color in a DataGrid?
Shows how to implement a colored background that react upon mouseover and selection. The implementation extends a label and overrides the 'updateDisplayList' method to draw some graphics as the background.
The last solution seems to be the one I preferred - because of the ability to see mouse effects applied to the cell. But still I liked the cleen implementation of the first one.

I couldn't resist of bringing combined solution, where I extends a Label, but listens for a Event.RENDER events instead of overriding the updateDisplayList method.

Sample Application


Sourcecode
Demonstrates how to use the renderer as a drop-in and inline itemRenderer.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" verticalAlign="middle" xmlns:tmp="component.dashboard.*"
creationComplete="init()">

<mx:Script>
private function init() : void {
myGrid.setFocus();
}
</mx:Script>
<mx:XML id="itemsXML">
<items>
<item name="Item 1" state="1" />
<item name="Item 2" state="0" />
<item name="Item 3" state="0" />
<item name="Item 4" state="1" />
<item name="Item 5" state="0" />
</items>
</mx:XML>

<mx:Style>
.centered {
text-align: center;
}
</mx:Style>

<mx:DataGrid id="myGrid" dataProvider="{itemsXML.item}" editable="true">
<mx:columns>
<mx:DataGridColumn dataField="@name" headerText="Name"
headerStyleName="centered"
itemRenderer="component.dashboard.TestItemRenderer"/>

<mx:DataGridColumn dataField="@state" headerText="Price"
textAlign="right" headerStyleName="centered">
<mx:itemRenderer>
<mx:Component>
<tmp:TestItemRenderer/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

</mx:Application>


CustomItemRenderer.as
Following is a CustomItemRenderer that can be extended to apply logic to decide if a cell is to be styled.

package dk.jacobve {

import mx.controls.Label;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.*;
import mx.events.FlexEvent;
import flash.events.Event;

public class CustomItemRenderer extends Label {

public function CustomItemRenderer {
//listen for render events
addEventListener(Event.RENDER, renderListener);
}

public function styleIt() : Boolean {
return false;
}

public function styleTrue() : void {
}

public function styleFalse() : void {
}

protected function renderListener(event:Event) : void {
if (listData != null) {
var grid:DataGrid = DataGrid(DataGridListData(listData).owner);
if (!grid.isItemHighlighted(data) && grid.selectedItem != data) {
if (styleIt()) {
styleTrue();
} else {
styleFalse();
}
} else {
styleFalse();
}
}
}
}
}


CustomItemRenderer extension
Shows an implementation using E4X on a xml data element to deside if the cell is to be colored red.

package dk.jacobve {

import mx.controls.Label;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.*;
import mx.events.FlexEvent;
import flash.events.Event;

public class TestItemRenderer extends CustomItemRenderer {
public override function styleIt() : Boolean {
return data.@state == "0";
}

public override function styleTrue() : void {
this.opaqueBackground = 0x33CC33;
}

public override function styleFalse() : void {
this.opaqueBackground = null;
}
}
}

2 comments:

Mac said...

I was also looking for a way to colorize datagrid rows, and decided to write my own custom component called "ColoredDataGrid" that extends DataGrid. It has two additional properties: rowColorField and rowColorFunction that allow you to either directly reference a data field that contains the color value you want to use, or use a function that can calculate the color however you like.

You can check out an example of ColoredDataGrid and get the source at my blog .

Mac

pat said...

I think there may be an error in the code. I had to add () after:
public function CustomItemRenderer