Problem Summery: One of the BBS developers asked a question about setting the background-color of separate header of DataGrid component. At first, I guessed that the style headerColors of DataGrid would help us. However, this style controls all headers’ background-color. Does headerStyleName of DataGridColumn would help us? Unfortunately, the answer was no. Setting the “background-color” of the style “myDataGridColumnStyle” which I assigned to “headerStyleName” took no effect. No resolution? I googled a lot, found no existing resolution.
Solution Summery: At last, I determined to dig into the DataGrid and related classes to solve this problem. After a hard working, I got the answer by rewriting the DataGridColumn class and DataGridHeaderBackgroundSkin class. It’s really a perfect resolution in my opinion. Anyone finds a bug; please left your comment here. Thank you!
Screenshot
Following is the source code of Catalog.as
package { public class Catalog { public static function get cataglog():XMLList { return catalog..CD; } private static var catalog:XML = <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Columbia</COMPANY> <PRICE>10.90</PRICE> <YEAR>1985</YEAR> </CD> <CD> <TITLE>Hide your heart</TITLE> <ARTIST>Bonnie Tylor</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS Records</COMPANY> <PRICE>9.90</PRICE> <YEAR>1988</YEAR> </CD> <CD> <TITLE>Greatest Hits</TITLE> <ARTIST>Dolly Parton</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>RCA</COMPANY> <PRICE>9.90</PRICE> <YEAR>1982</YEAR> </CD> <CD> <TITLE>Still got the blues</TITLE> <ARTIST>Gary More</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Virgin redords</COMPANY> <PRICE>10.20</PRICE> <YEAR>1990</YEAR> </CD> <CD> <TITLE>Eros</TITLE> <ARTIST>Eros Ramazzotti</ARTIST> <COUNTRY>EU</COUNTRY> <COMPANY>BMG</COMPANY> <PRICE>9.90</PRICE> <YEAR>1997</YEAR> </CD> <CD> <TITLE>One night only</TITLE> <ARTIST>Bee Gees</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Polydor</COMPANY> <PRICE>10.90</PRICE> <YEAR>1998</YEAR> </CD> <CD> <TITLE>Sylvias Mother</TITLE> <ARTIST>Dr.Hook</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS</COMPANY> <PRICE>8.10</PRICE> <YEAR>1973</YEAR> </CD> <CD> <TITLE>Maggie May</TITLE> <ARTIST>Rod Stewart</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Pickwick</COMPANY> <PRICE>8.50</PRICE> <YEAR>1990</YEAR> </CD> <CD> <TITLE>Romanza</TITLE> <ARTIST>Andrea Bocelli</ARTIST> <COUNTRY>EU</COUNTRY> <COMPANY>Polydor</COMPANY> <PRICE>10.80</PRICE> <YEAR>1996</YEAR> </CD> <CD> <TITLE>When a man loves a woman</TITLE> <ARTIST>Percy Sledge</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Atlantic</COMPANY> <PRICE>8.70</PRICE> <YEAR>1987</YEAR> </CD> <CD> <TITLE>Black angel</TITLE> <ARTIST>Savage Rose</ARTIST> <COUNTRY>EU</COUNTRY> <COMPANY>Mega</COMPANY> <PRICE>10.90</PRICE> <YEAR>1995</YEAR> </CD> <CD> <TITLE>1999 Grammy Nominees</TITLE> <ARTIST>Many</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Grammy</COMPANY> <PRICE>10.20</PRICE> <YEAR>1999</YEAR> </CD> <CD> <TITLE>For the good times</TITLE> <ARTIST>Kenny Rogers</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Mucik Master</COMPANY> <PRICE>8.70</PRICE> <YEAR>1995</YEAR> </CD> <CD> <TITLE>Big Willie style</TITLE> <ARTIST>Will Smith</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Columbia</COMPANY> <PRICE>9.90</PRICE> <YEAR>1997</YEAR> </CD> <CD> <TITLE>Tupelo Honey</TITLE> <ARTIST>Van Morrison</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Polydor</COMPANY> <PRICE>8.20</PRICE> <YEAR>1971</YEAR> </CD> <CD> <TITLE>Soulsville</TITLE> <ARTIST>Jorn Hoel</ARTIST> <COUNTRY>Norway</COUNTRY> <COMPANY>WEA</COMPANY> <PRICE>7.90</PRICE> <YEAR>1996</YEAR> </CD> <CD> <TITLE>The very best of</TITLE> <ARTIST>Cat Stevens</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Island</COMPANY> <PRICE>8.90</PRICE> <YEAR>1990</YEAR> </CD> <CD> <TITLE>Stop</TITLE> <ARTIST>Sam Brown</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>A and M</COMPANY> <PRICE>8.90</PRICE> <YEAR>1988</YEAR> </CD> <CD> <TITLE>Bridge of Spies</TITLE> <ARTIST>T`Pau</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Siren</COMPANY> <PRICE>7.90</PRICE> <YEAR>1987</YEAR> </CD> <CD> <TITLE>Private Dancer</TITLE> <ARTIST>Tina Turner</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Capitol</COMPANY> <PRICE>8.90</PRICE> <YEAR>1983</YEAR> </CD> <CD> <TITLE>Midt om natten</TITLE> <ARTIST>Kim Larsen</ARTIST> <COUNTRY>EU</COUNTRY> <COMPANY>Medley</COMPANY> <PRICE>7.80</PRICE> <YEAR>1983</YEAR> </CD> <CD> <TITLE>Pavarotti Gala Concert</TITLE> <ARTIST>Luciano Pavarotti</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>DECCA</COMPANY> <PRICE>9.90</PRICE> <YEAR>1991</YEAR> </CD> <CD> <TITLE>The dock of the bay</TITLE> <ARTIST>Otis Redding</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Atlantic</COMPANY> <PRICE>7.90</PRICE> <YEAR>1987</YEAR> </CD> <CD> <TITLE>Picture book</TITLE> <ARTIST>Simply Red</ARTIST> <COUNTRY>EU</COUNTRY> <COMPANY>Elektra</COMPANY> <PRICE>7.20</PRICE> <YEAR>1985</YEAR> </CD> <CD> <TITLE>Red</TITLE> <ARTIST>The Communards</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>London</COMPANY> <PRICE>7.80</PRICE> <YEAR>1987</YEAR> </CD> <CD> <TITLE>Unchain my heart</TITLE> <ARTIST>Joe Cocker</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>EMI</COMPANY> <PRICE>8.20</PRICE> <YEAR>1987</YEAR> </CD> </CATALOG>; } }
And following is the source code of DataGridColumn.as
package com.edison.controls.dataGridClasses { import flash.events.Event; import mx.controls.dataGridClasses.DataGridColumn; import mx.core.mx_internal; import mx.utils.UIDUtil; use namespace mx_internal; [Style(name="headerColors", type="Array", arrayType="uint", format="Color", inherit="yes")] public dynamic class DataGridColumn extends mx.controls.dataGridClasses.DataGridColumn { public function DataGridColumn(columnName:String=null) { super(columnName); } public var uid:String = UIDUtil.createUID(); override mx_internal function setWidth(value:Number):void { super.setWidth(value); dispatchEvent(new Event("widthChanged")); } } }
Following is the source code of DataGridHeaderBackgroundSkin.as
package com.edison.skins { import flash.display.GradientType; import flash.display.Graphics; import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix; import mx.controls.DataGrid; import mx.controls.dataGridClasses.DataGridColumn; import mx.controls.dataGridClasses.DataGridHeader; import mx.controls.listClasses.IListItemRenderer; import mx.core.mx_internal; import mx.skins.halo.DataGridHeaderBackgroundSkin; import mx.styles.StyleManager; import mx.utils.UIDUtil; use namespace mx_internal; public class DataGridHeaderBackgroundSkin extends mx.skins.halo.DataGridHeaderBackgroundSkin { public function DataGridHeaderBackgroundSkin() { super(); } private var columnBackgroundMap:Object = new Object(); override protected function updateDisplayList(w:Number, h:Number):void { super.updateDisplayList(w,h); if(w == 0) return; var dataGridHeader:DataGridHeader = DataGridHeader(parent.parent); var dataGrid:DataGrid = DataGrid(dataGridHeader.owner); var visibleColumns:Array = dataGrid.getAllVisibleColumns(); var headerItems:Array = dataGridHeader.rendererArray; for each(var column:DataGridColumn in visibleColumns) { var colors:Array = column.getStyle("headerColors"); var headerItem:IListItemRenderer = headerItems[column.colNum] var x:Number = headerItem.x; w = column.width; var uid:String = UIDUtil.getUID(column); var sprite:Sprite = columnBackgroundMap[uid]; if(sprite == null) { sprite = new Sprite(); parent.addChild(sprite); columnBackgroundMap[uid] = sprite; } sprite.x = x; if(colors != null) { var g:Graphics = sprite.graphics; g.clear(); var matrix:Matrix = new Matrix(); matrix.createGradientBox(w, h + 1, Math.PI/2, 0, 0); StyleManager.getColorNames(colors); colors = [ colors[0], colors[0], colors[1] ]; var ratios:Array = [ 0, 60, 255 ]; var alphas:Array = [ 1.0, 1.0, 1.0 ]; g.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix); g.lineStyle(0, 0x000000, 0); g.moveTo(0, 0); g.lineTo(w, 0); g.lineTo(w, h - 0.5); g.lineStyle(0, getStyle("borderColor"), 100); g.lineTo(0, h - 0.5); g.lineStyle(0, 0x000000, 0); g.endFill(); } column.addEventListener("widthChanged",columnWidthChangedHandler); } } private function columnWidthChangedHandler(event:Event):void { invalidateDisplayList(); } } }
Last one is the source code of DataGridHeaderBackgroundProblem.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:dataGridClasses="com.edison.controls.dataGridClasses.*" layout="absolute" > <mx:Panel title="Set Background-color for Headers of DataGrid" width="100%" height="100%"> <mx:DataGrid dataProvider="{Catalog.cataglog}" headerBackgroundSkin="com.edison.skins.DataGridHeaderBackgroundSkin" height="100%" > <mx:columns> <dataGridClasses:DataGridColumn dataField="ARTIST" headerText="Artist" headerColors="{[0xFF9900,0xFFFFFF]}"/> <dataGridClasses:DataGridColumn dataField="TITLE" headerText="Title" headerColors="{[0x99FF00,0xFFFFFF]}"/> <dataGridClasses:DataGridColumn dataField="YEAR" headerText="Year" headerColors="{[0x0099FF,0xFFFFFF]}"/> </mx:columns> </mx:DataGrid> </mx:Panel> </mx:Application>
[...] 之前介绍过Flex中设置DataGrid背景颜色的例子(Flex中利用backgroundColor样式设置DataGrid控件每一个DataGridColumn对象背景颜色的例子)以及Flex中如何实现DataGrid控件头部高度等例子,在Set Background-color for Headers of DataGrid,介绍了如何实现自定义DataGrid头部背景颜色,有需要的可以下来直接用。下面是效果图: [...]
[...] Article URL: Set Background-color for Headers of DataGrid [...]
Very useful, thx
SOOOO helpful! Thanks a million… Nay! a billion!!
Thank’s! Amazing!
Thank you very much for this work ! It is very useful and don t exist another answer of this question on the web
Very Useful. But when i set lockedColumnCount, the datagrid is not showing. Can anyone help me. Thanks.
It is useful. Thanks a lot.
But when we set lockedColumnCount, it does not work.
Please provide a solution with a grid using the lockedColumnCount. Thanks
Yes, unfortunately it’s true..
Setting lockedColumnCount >= 1 breaks this.
I’m trying to solve, if I got a solution, I will post.
Firstly, the original post have a performance issue, the listener were added a lot of times to the same DataGridColumn. To fix this, I did:
On the ExtendedDataGridColumn, I put a new property as folows:
var isSkinEventListenerSet: Boolean = false;
and changed the addEventListener line on the skin to:
if (column is ExtendedDataGridColumn)
{
if (! ExtendedDataGridColumn(column).isSkinEventListenerSet)
{
column.addEventListener(“widthChanged”,columnWidthChangedHandler);
ExtendedDataGridColumn(column).isSkinEventListenerSet = true;
}
}
To solve the lockedColumnCount problem, I did:
On the datagrid, I put a method like this:
protected function onScroll(event: ScrollEvent):void {
if (event.direction = ScrollEventDirection.HORIZONTAL)
{
datagrid.columns[datagrid.lockedColumnCount].dispatchEvent(new Event(“widthChanged”));
datagrid.columns[0].dispatchEvent(new Event(“widthChanged”));
}
}
And on the initialization of the Datagrid, I put:
datagrid.addEventListener(Event.SCROLL, onScroll);
Sorry for the lack of code formatting and coloring, I don’t know how to do that here…
This worked ok for me, I hope it works for you too. Thanks!
@BrunoJCM
Great work! Thanks a lot!!!
Oh, There’s a bug in my code!
Line
———————
if (event.direction = ScrollEventDirection.HORIZONTAL)
———————
Should be
———————
if (event.direction == ScrollEventDirection.HORIZONTAL)
———————
And I realized I had modified another piece of the original code, but I don’t know if it’s necessary:
Instead of
———————
var colors:Array = column.getStyle(“headerColors”);
var headerItem:IListItemRenderer = headerItems[column.colNum]
———————
I put
———————
var headerItem:IListItemRenderer = null;
for each(var possibleHeaderItem:DataGridItemRenderer in headerItems)
{
if ( column == possibleHeaderItem.data)
{
headerItem = possibleHeaderItem;
}
}
———————
I think it’s the same (slowly), but I have no time to test it now..
Nice, but not perfect though. It doesn’t work when you use horizontal scroll.
[...] have introduced how to set background color for the headers of DataGrid in Flex, sometimes, we also need to get the row and column value in DataGrid, do you know how to do it? The [...]
Hi,
thanks a lot , for the solution , the gradient color comes fine for the datagrid column , but my requirement is when the user clicks on any other column the color for that column should change ..how do i do that …i have tried seting style on header release event of datagrid ..not working
..an suggestions….
Trying this on Flex 4.0. Getting the below error. Any suggestions?
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.skins.halo::DataGridHeaderBackgroundSkin/updateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\skins\halo\DataGridHeaderBackgroundSkin.as:75]
at com.edison.skins::DataGridHeaderBackgroundSkin/updateDisplayList()[C:\Sam\Adobe Flash Builder 4\TestDataGrid\src\com\edison\skins\DataGridHeaderBackgroundSkin.as:31]
at mx.skins::ProgrammaticSkin/validateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\skins\ProgrammaticSkin.as:503]
at mx.managers::LayoutManager/validateClient()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:932]
at mx.core::UIComponent/validateNow()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7631]
at mx.controls.dataGridClasses::DataGridBase/updateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\controls\dataGridClasses\DataGridBase.as:594]
at mx.controls::DataGrid/updateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:1741]
at mx.controls.listClasses::ListBase/validateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\controls\listClasses\ListBase.as:3962]
at mx.managers::LayoutManager/validateDisplayList()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:663]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:718]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]