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>

February 18th, 2009
Ntt.cc 








Posted in
Tags: 
RSS Feed
Email Feed
[...] 之前介绍过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..