Skinning the Flash DataGrid
For a current project, I needed a datagrid with partially transparent rows. No problem I thought - I'll just extend the V2 datagrid and write my own versions of the required methods. All so simple in theory, not so simple in real life. There are two things that must be made transparent, the general component background and the background of each row. I first tried overwriting the methods I thought to control this but that did not work. The one who made the datagrid never thought that anyone would ever want partially transparent gridrows. The component just does not contain any code that enables this. Another thing is that no matter what you do, you cannot re-pack or alter the datagrid assets that are used to draw the grid.
The grids assets are stuck inside a SWC file and even if you rename the SWC to ZIP and extract the contents, you'll find some of the assets to be inside a SWF. Reversing this SWF is out of the question. I've browsed the whole class hierarchy and I cannot find a place where the component background is drawn using scripting, so I've concluded that it must be embedded within the asset SWF. The same goes for the gridrow class. In theory, I could just change the beginFill-metod that tells how to draw the rows, but for some reason this won't work. I tell it to use Alpha, but the setting is just ignored. Where to go next?
I browsed Flashcoders and searched the web. I found plenty of questions, but no solution. Most of these solutions required that you did work directly on the movieClips inside the grid and that's also what I've concluded must be the solution. It is with the datagrid rows as with so many other components - they require a one frame pause to redraw all contents. Have you heard the saying "If in doubt - wait one frame"? If not, just try it and in maybe 50% of all cases, waiting one frame will solve your problems. You could solve this using Intervals, but as you also may know - too many intervals may kill your Flash movie. If they are not deleted properly, you'll end up with an unresponsive application and deleting them can be a hassle. To the rescue comes my rather manual WaitXframes-class. Just specify a location to make a temporary movieClip and the handler to run once finished waiting. Easy to clean up and no intervals used. So here's my solution:
import mx.controls.DataGrid;
import mx.styles.CSSStyleDeclaration;
import no.netron.utils.WaitXframes;
// Attach DataGrid
var rootObject:MovieClip = _root;
rootObject.createClassObject(DataGrid,"theGrid",rootObject.getNextHighestDepth());
var my_dg = rootObject.theGrid;
my_dg.setStyle("alternatingRowColors", Array(0xEAEFF4, 0xF8FAFB));
// Add some dummy data
var myDP_array:Array = new Array();
myDP_array.push({name:"Clark",checked:false, score:3135});
myDP_array.push({name:"Bruce",checked:true, score:403});
myDP_array.push({name:"Peter",checked:false, score:25});
my_dg.dataProvider = myDP_array;
// Move away from upper corner
my_dg.setSize(350, 200);
my_dg.move(20, 40);
// Turn off transparency for the main datagrid background clip
my_dg.border_mc._alpha = 0;
// Function to adjust transpareny of each row in grid
function fixAlpha(){
var i = 10; // Rows always start on row ten
while(my_dg.content_mc["listRow"+i] != undefined){
my_dg.content_mc["listRow"+i]._alpha = 55;
i++;
}
}
s = new WaitXframes(rootObject,1,"fixAlpha",this);
I can't post the FLA for this example without breaking the Macromedia EULA, but just add a datagrid to your library and paste this code in frame 1 to see it working. You may also want to add a background image to really see the transparency. This was also the first project where I used the XRay debugger extensively. Great tool for the output I get from the debugger in the Flash IDE is worthless.
If anyone reading this has a different take, please post it in the comments. I feel this is a downright dirty way to solve such a problem, but for now it's the only way I've found...
Comments
I can completely relate to the difficulty of skinning the v2 components. Since these were the base for Flex 1.x components, it's not much easier there. I know this isn't of any consolation right now, but for what it's worth, almost all the Flex 2 components have numerous transparency options right out of the box. I put together a simple example that mirrors your problem in MXML. I also included an extra few lines of code to make the "true/false" column into a CheckBox.
http://weblogs.macromedia.com/khoyt/files/transparent-grid.gif (source)
Posted by: Kevin Hoyt | February 18, 2006 12:01 AM
thank you so much. very insightful... :) STEF
Posted by: stef | February 18, 2006 02:16 AM
Hi Kevin,
Thanks for posting the example! "background-alpha" looks great, but yeah - can't use Flex 2 just yet :) Maybe there will be an update to the documentation with it?
Most styles applying to the DataGrid can be found under the help entries for the List Class, but there's no link in the docs from the DataGrid to the List class? It would be really useful to have one page per class/component listing all the valid styles for each component, complete with what classes they inherit the styles from. Now I have to hunt through the class inheritance tree/docs to find all the supported styles.
J
Posted by: Jensa | February 18, 2006 09:23 AM
Standardizing the class library into a consistent and cohesive framework that can be leveraged across both Flex and Flash authoring is a big part of what the whole Flex Framework 2 is all about. I can't say (because I don't know) what the Flash authoring team has up their sleeves in the future, but I would expect this to be on this list.
As it stands today, Flex 1.x has done a great job of taking this first step. Take a look at the DataGrid documentation (Flex) below. If you scroll down you'll see all the styles you can apply including those styles that are inherited.
http://livedocs.macromedia.com/flex/15/asdocs_en/mx/controls/DataGrid.html
Posted by: Kevin Hoyt | February 19, 2006 03:07 AM
Try this:
_global.styles.ScrollSelectList.backgroundColor = undefined;
mx.controls.listclasses.SelectableRow.prototype.drawRowFill = function(mc:MovieClip, newClr:Number):Void {
mc.clear();
if (newClr == undefined) {
mc.beginFill(0xABCDEF, 0);
} else {
mc.beginFill(newClr);
}
mc.drawRect(1, 0, this.__width, this.__height);
mc.endFill();
mc._width = this.__width;
mc._height = this.__height;
};
and don't use
mydg.setStyle("alternatingRowColors",
See:
http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?href=00003700.html&single=true
FYI, WaitXframes is not neccessary in your code.
Try:
my_dg.doLater(this, "fixAlpha");
PhilFlash
http://philflash.inway.fr
Posted by: PhilFlash | February 19, 2006 12:01 PM
Kevin: Inherited Styles and Effects and more = Great! I really should take some days off to get better into Flex/AS3, but I'm swamped with work :)
PhilFlash: I tried using your prototype, but it didn't work? I added it just after my import-statements before instantiating my grid, but it apparently has no effect? Any suggestions?
(ps: the code for alternatingRowColors was found in one of your code examples. Your homepage is a great resource for skinning components!)
J
Posted by: Jensa | February 19, 2006 12:48 PM
Muchas gracias!
Thanks for share your knowledge with the other people.
Posted by: Spook | March 4, 2006 06:17 PM
Nice work with this, but one small question: How can i make a dataGrid that already exist on the stage to be transparent? i tried to modifie a little bit, but no changes...Any idea?
Posted by: IOG | April 12, 2006 04:10 PM
IOG: this should work well for a datagrid placed directly on stage as well. Just make sure you use the correct instance name (replace my_dg with the instance name you use) and all should be fine.
J
Posted by: Jensa | April 18, 2006 11:42 AM
I added a checkbox control into the datagrid, however when I set the _alpha property the checkboxes disappeared too? any ideas?
Posted by: Ed | July 25, 2006 09:32 PM
Very helpful!
But I think that the best way to do it is the next:
//Alpha background really
dg.content_mc["listRow"+i].backGround._alpha = 55;
//Invisible, useful for print without background
dg.content_mc["listRow"+i].backGround._visible = false;
Posted by: Dano | August 28, 2006 05:52 AM
Very helpful!
I like to use at this way:
//Visible false, very helpful to print
dg.content_mc["listRow"+i].backGround._visible = false;
//Really alpha background
dg.content_mc["listRow"+i].backGround._alpha = 55;
D
Posted by: Dano | August 28, 2006 06:01 AM
I'm just beginning to delve into the world of Flash and I must say I am quite excited to see that Flash has support for datagrids. I have always been very disappointed with all of the PHP datagrids I've been able to find.
Posted by: Brad | October 4, 2006 12:32 AM
Hi,
my name is kaan
i want use my grid html code. I how do?
Please sen me mail :(
Posted by: Kaan | October 12, 2006 08:26 AM
Hi, Is it possible to also make the header row transparent?
If so, how?
Thanks.
Geoff
Posted by: Geoff | February 4, 2007 06:15 AM