Flex Fun - Advanced DataGrid Topics
| We are going to start by looking at an example program that shows off what we are going to learn today. You will notice that the datagrid doesn't have any header labels or vertical grid lines. I have also skinned the scroll bar and changed some colors. All the data comes from two xml files that we will write here in a minute. The data shown in the datagrid is done in a couple different ways, which we will go over later. |
Creating XML Data
The first item to take care of is getting our data together. This done using a couple of xml files. The first file has the people and their favorite game. The second xml file is a list of games that people can have for their favorite game and information about that game.
The first file is people.xml.
<?xml version="1.0"?>
<people>
<person>
<name>
<first>Charlie</first>
<last>Key</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<favGameID>1</favGameID>
</person>
<person>
<name>
<first>Brandon</first>
<last>Cannaday</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>CFO</title>
<favGameID>3</favGameID>
</person>
<person>
<name>
<first>Michael</first>
<last>Kuehl</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>CTO</title>
<favGameID>5</favGameID>
</person>
<person>
<name>
<first>Kevin</first>
<last>Putvin</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>Lazy Guy</title>
<favGameID>2</favGameID>
</person>
<person>
<name>
<first>Richard</first>
<last>Key</last>
</name>
<info>
<age>20</age>
<sex>Male</sex>
</info>
<title>Underling</title>
<favGameID>4</favGameID>
</person>
<person>
<name>
<first>Caroline</first>
<last>Andersen</last>
</name>
<info>
<age>23</age>
<sex>Female</sex>
</info>
<title>Supporter</title>
<favGameID>6</favGameID>
</person>
</people>
<people>
<person>
<name>
<first>Charlie</first>
<last>Key</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<favGameID>1</favGameID>
</person>
<person>
<name>
<first>Brandon</first>
<last>Cannaday</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>CFO</title>
<favGameID>3</favGameID>
</person>
<person>
<name>
<first>Michael</first>
<last>Kuehl</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>CTO</title>
<favGameID>5</favGameID>
</person>
<person>
<name>
<first>Kevin</first>
<last>Putvin</last>
</name>
<info>
<age>23</age>
<sex>Male</sex>
</info>
<title>Lazy Guy</title>
<favGameID>2</favGameID>
</person>
<person>
<name>
<first>Richard</first>
<last>Key</last>
</name>
<info>
<age>20</age>
<sex>Male</sex>
</info>
<title>Underling</title>
<favGameID>4</favGameID>
</person>
<person>
<name>
<first>Caroline</first>
<last>Andersen</last>
</name>
<info>
<age>23</age>
<sex>Female</sex>
</info>
<title>Supporter</title>
<favGameID>6</favGameID>
</person>
</people>
And the second is games.xml.
<?xml version="1.0"?>
<games>
<game id="1">
<name>World of Warcraft</name>
<publisher>Vivendi Universal</publisher>
<developer>Blizzard</developer>
<imageURL>/files/gamepics/wow_small.jpg</imageURL>
</game>
<game id="2">
<name>Halo 2</name>
<publisher>Microsoft Game Studios</publisher>
<developer>Bungie Studios</developer>
<imageURL>/files/gamepics/halo_small.jpg</imageURL>
</game>
<game id="3">
<name>Half Life 2</name>
<publisher>Valve Corporation</publisher>
<developer>Valve Corporation</developer>
<imageURL>/files/gamepics/hl_2_small.jpg</imageURL>
</game>
<game id="4">
<name>Gears of War</name>
<publisher>Microsoft Game Studios</publisher>
<developer>Epic Games</developer>
<imageURL>/files/gamepics/gears_of_war_small.jpg
</imageURL>
</game>
<game id="5">
<name>The Elder Scrolls IV: Oblivion</name>
<publisher>2K Games</publisher>
<developer>Bethesda Game Studios</developer>
<imageURL>/files/gamepics/oblivion_small.jpg</imageURL>
</game>
<game id="6">
<name>The Legend of Zelda: Twilight Princess</name>
<publisher>Nintendo EAD</publisher>
<developer>Nintendo</developer>
<imageURL>/files/gamepics/zelda_small.jpg</imageURL>
</game>
</games>
<games>
<game id="1">
<name>World of Warcraft</name>
<publisher>Vivendi Universal</publisher>
<developer>Blizzard</developer>
<imageURL>/files/gamepics/wow_small.jpg</imageURL>
</game>
<game id="2">
<name>Halo 2</name>
<publisher>Microsoft Game Studios</publisher>
<developer>Bungie Studios</developer>
<imageURL>/files/gamepics/halo_small.jpg</imageURL>
</game>
<game id="3">
<name>Half Life 2</name>
<publisher>Valve Corporation</publisher>
<developer>Valve Corporation</developer>
<imageURL>/files/gamepics/hl_2_small.jpg</imageURL>
</game>
<game id="4">
<name>Gears of War</name>
<publisher>Microsoft Game Studios</publisher>
<developer>Epic Games</developer>
<imageURL>/files/gamepics/gears_of_war_small.jpg
</imageURL>
</game>
<game id="5">
<name>The Elder Scrolls IV: Oblivion</name>
<publisher>2K Games</publisher>
<developer>Bethesda Game Studios</developer>
<imageURL>/files/gamepics/oblivion_small.jpg</imageURL>
</game>
<game id="6">
<name>The Legend of Zelda: Twilight Princess</name>
<publisher>Nintendo EAD</publisher>
<developer>Nintendo</developer>
<imageURL>/files/gamepics/zelda_small.jpg</imageURL>
</game>
</games>
If you want to make this exact example work on your local computer you will need to append
http://blog.paranoidferret.com to the beginning of each image url.Creating The Flex Interface
Creating the Flex interface is a simple task in which nothing really complex is done. I created a new application and added a panel to it. This panel holds all the other user interface components. We have a label at the top of the panel telling everyone that the information displayed is our favorite games. Below this is our datagrid which will hold the bulk of the data. After the datagrid there are a couple items to show details of a game including a large image, which is the image url from our xml data. The following code is our simple interface.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="530" height="610"
viewSourceURL="/files/AdvancedDatagrid.mxml">
<mx:Panel width="530" height="610" layout="absolute"
title="Advanced Datagrids">
<mx:Label horizontalCenter="0" y="1"
text="Our Favorite Games"
fontSize="16" fontWeight="bold"/>
<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0">
<mx:columns>
<mx:DataGridColumn headerText="Name" width="75">
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Info" width="80"/>
<mx:DataGridColumn headerText="Favorite Game"/>
</mx:columns>
</mx:DataGrid>
<mx:Image x="10" y="318" width="300" height="240"
id="imgGameScreen"/>
<mx:Label x="10" y="293" fontWeight="bold" fontSize="13"
id="lblGameName"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher" />
</mx:Panel>
</mx:Application>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="530" height="610"
viewSourceURL="/files/AdvancedDatagrid.mxml">
<mx:Panel width="530" height="610" layout="absolute"
title="Advanced Datagrids">
<mx:Label horizontalCenter="0" y="1"
text="Our Favorite Games"
fontSize="16" fontWeight="bold"/>
<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0">
<mx:columns>
<mx:DataGridColumn headerText="Name" width="75">
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Info" width="80"/>
<mx:DataGridColumn headerText="Favorite Game"/>
</mx:columns>
</mx:DataGrid>
<mx:Image x="10" y="318" width="300" height="240"
id="imgGameScreen"/>
<mx:Label x="10" y="293" fontWeight="bold" fontSize="13"
id="lblGameName"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher" />
</mx:Panel>
</mx:Application>
Well that takes care of the beginning of our application.
Binding the XML Data
Now we get to have little fun. Binding the xml data to the datagrid isn't that bad. We take advantage of some components that make our life much easier. The first step is creating an object from the xml source file. Below is the code to accomplish this. It creates a
<mx:Model> (click here for more info on this tag) object that represents the xml data from the source file.<mx:Model id="people" source="/data/people.xml"/>
Next we create another component of type
<mx:XML>. This, as you can probably figure out, makes a XML object. I don't use a data model this time because we are going to use the games xml data a little differently. We will take advantage of one of the xml tricks we can do in Flex and we also do not need to bind the data to a DataGrid. Grabbing our games xml data looks like:<mx:XML id="games" source="/data/games.xml"/>
Both of the above tags will go right after the opening application tag.
Now we can simply bind the datagrid to our data model of the people from our xml data. The only thing we need to do is make sure that we bind to the correct property. Using
<mx:Model> creates an object of the entire xml data, therefore we need to go down one level to the person property of our people model. The new datagrid looks like:<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}">
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}">
This takes care of binding the data but none of it is going to show up yet because we haven't added any rendering code. The next thing we are going to do is display the data we now have.
Displaying DataGrid Data
This section is going to introduce a few new concepts. The first feature we are going to look at and use are label functions. A lot of the time we have complex data that we want to display in our datagrids and using the
dataField property just doesn't cut it. A label function will take in the current item being processed and the data grid column and will return a string. The returned string is what will be displayed in the cell.We are going to use a label function for the info column. To declare we are going to use one, all that is needed is to set the
labelFunction property. This is set to displayPersonInfo which is an actionscript function we will create in just a moment. The new datagrid column code looks like the following.<mx:DataGridColumn headerText="Info" width="80"
labelFunction="displayPersonInfo"/>
labelFunction="displayPersonInfo"/>
Next we create the actionscript function in a new
<mx:Script> tag which goes right beneath the opening application tag. Inside our function we are going to concatenate the two pieces of info (check the xml structure to see what I mean) from our item. In the code below you can see the two parameters that I brought in which were explained in the earlier paragraph. We use the item parameter and grab item.info.age and item.info.sex and return them as a combined string. That is the basics of a label function. Also note that any label function needs to take in both parameters (even if they're not used) and return a string.<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
private function displayPersonInfo(item:Object,
col:DataGridColumn):String
{
return item.info.age + " " + item.info.sex;
}
]]>
</mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
private function displayPersonInfo(item:Object,
col:DataGridColumn):String
{
return item.info.age + " " + item.info.sex;
}
]]>
</mx:Script>
At least we are displaying something now. Lets move on to the harder display components. For the other two columns we are going to use item renderers. An item renderer is a set of custom code that displays the data in a column in particular way using mxml components and/or your own custom components. There are four different kinds of item renderers: drop-in, inline, reusable, and component. In this tutorial we use two of them - inline and component. Look for a snippet tutorial in future going over all of them.
The first one we use is the inline item renderer. You might have noticed when we created the interface that the first DataGridColumn had an opening and closing tag. Well this was on purpose. We add the item renderer inside the DataGridColumn tags, hence the name inline. After the opening tag we add a
<mx:itemRenderer> telling Flex that we are going to define the itemRenderer property right here. Inside the itemRenderer tag we build a <mx:Component>. Inside the <mx:Component> tag we can use all the normal ui components we have at our disposal. Now to refer to the current row data we use the data object. In ours we simply have two <Label> components added to a <VBox> and bind the text to the first and last names. Below you will see our new complete DataGridColumn code.<mx:DataGridColumn headerText="Name" width="75">
<mx:itemRenderer>
<mx:Component>
<mx:VBox verticalGap="2">
<mx:Label text="{data.name.first}" />
<mx:Label text="{data.name.last}" />
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:itemRenderer>
<mx:Component>
<mx:VBox verticalGap="2">
<mx:Label text="{data.name.first}" />
<mx:Label text="{data.name.last}" />
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
The other item renderer we use is going to be its own mxml component. This means we are going to create an entire new file. This component is going to use data from the row and also data from our games xml file to display a small picture and name of the game. We create a new file which we name "ImageRenderer.mxml" and I put it in a folder named "comp" - this doesn't matter except when you reference it. In this file we are going to create a simple custom component which is based off of a HBox and has an
<mx:Image> and a <mx:Label> in it. I also add the same XML tag as we have in the main file because we are going to need this data. The basic structure of the component looks like:<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
verticalAlign="top">
<mx:XML id="games" source="/data/games.xml" />
<mx:Image
scaleX=".25" scaleY=".25"/>
<mx:Label
width="250" />
</mx:HBox>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
verticalAlign="top">
<mx:XML id="games" source="/data/games.xml" />
<mx:Image
scaleX=".25" scaleY=".25"/>
<mx:Label
width="250" />
</mx:HBox>
Everything looks alright except we aren't setting any data. We set the source of the image to something a little complex - earlier I mentioned we were going to use a cool XML object feature and here is the first place we use it. First off the image tag now looks like:
<mx:Image
source="{games.game.(@id == data.favGameID).imageURL}"
scaleX=".25" scaleY=".25"/>
source="{games.game.(@id == data.favGameID).imageURL}"
scaleX=".25" scaleY=".25"/>
This looks a little crazy but we'll step through it. Ignoring
(@id == data.favGameID) and it looks like we are grabbing an imageURL from the games XML object. Which is exactly what is going on, but we need to tell it which game in the xml. To do this we use the id attribute we defined for each of the games in the xml file. Also in our people xml file we referred to each person's favorite game by the id so we can use this to match up the correct game. Then all that (@id == data.favGameID) is saying is that we are going use the id attribute on game (because it comes right after that property) and get the game with id equal to data.favGameID, this is the same data object as before.That takes care of the image, on to the label. We use the same technique as above but we just get the game name now. The new Label looks like the code below.
<mx:Label
text="{games.game.(@id == data.favGameID).name}"
width="250" />
text="{games.game.(@id == data.favGameID).name}"
width="250" />
This completes our new component. The whole file now looks like:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
verticalAlign="top">
<mx:XML id="games" source="/data/games.xml" />
<mx:Image
source="{games.game.(@id == data.favGameID).imageURL}"
scaleX=".25" scaleY=".25"/>
<mx:Label
text="{games.game.(@id == data.favGameID).name}"
width="250" />
</mx:HBox>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
verticalAlign="top">
<mx:XML id="games" source="/data/games.xml" />
<mx:Image
source="{games.game.(@id == data.favGameID).imageURL}"
scaleX=".25" scaleY=".25"/>
<mx:Label
text="{games.game.(@id == data.favGameID).name}"
width="250" />
</mx:HBox>
To hook this into our last datagrid column we simply set the
itemRenderer property equal to the name of this component. In my case comp.ImageRenderer - remembering that I put it in the "comp" folder so I have to put this at the beginning. The DataGridColumn code now looks like the following.<mx:DataGridColumn headerText="Favorite Game"
itemRenderer="comp.ImageRenderer"/>
itemRenderer="comp.ImageRenderer"/>
We now have a datagrid fully displaying all the information. Take a break and grab a drink...Ok we're back - on to the next part.
Display Selected Data
In this part we are going to display the large image and data about the currently selected game. We will use the xml feature we went over earlier extensively in this section. I am not going to go real far in depth about these components because it is all things that we have done before.
The larger image will have its
source set to the image url of the currently selected item's favorite game. The labels will have their values set in the same fashion. To get to the selected item's favorite game id we will use dgPeeps.selectedItem.favGameID. This grabs the currently selected item from the datagrid and then gets the favGameID from the selected item. So the whole new lower ui section now looks like.<mx:Image x="10" y="318" width="300" height="240"
id="imgGameScreen"
source=
"{games.game.(@id ==
dgPeeps.selectedItem.favGameID).imageURL}"/>
<mx:Label x="10" y="293"
fontWeight="bold" fontSize="13" id="lblGameName"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).name}"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).developer}"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).publisher}"/>
id="imgGameScreen"
source=
"{games.game.(@id ==
dgPeeps.selectedItem.favGameID).imageURL}"/>
<mx:Label x="10" y="293"
fontWeight="bold" fontSize="13" id="lblGameName"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).name}"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).developer}"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).publisher}"/>
Sorry about the formatting atrocity (we have a limited page width to work with). Next we get to do some styling and skinning.
Styling the Application
Adobe has given Flex some great features when it comes to styling an application, I will touch on just a small number of them in this tutorial. The first change we are going to make is simply setting a property of the datagrid. We set the
showHeaders property to false to remove the header row. The new DataGrid component has the following code.<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}"
showHeaders="false">
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}"
showHeaders="false">
The rest of our changes are going to be done in a new file which is going to be a css file. Flex has the ability to use css syntax to define the style of components. You can define styles for components or create css classes and use them in your mxml to give a component a certain style just like in html. My css file is in a folder called "assets" and is named "app.css".
In this file we are going to start by actually embedding a new font from a .swf file - which is included in the zip file. In "fonts.swf" the font face "Myriad Web" is defined. To use this we need to define the different font faces we are going to use. I set up three different font faces one for normal, one for bold, and one for italics. To learn more about fonts in Flex check out the Adobe livedocs here. The following code goes in our css file and will use the "fonts.swf" to create the new font faces.
/** Font Info **/
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontWeight: bold;
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontStyle: italic;
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontWeight: bold;
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontStyle: italic;
}
To use these we will set some styles for the Application, we set the
font-family and font-size. To use the new font family I refer to it using the fontFamily name in the @font-face code. The Application style is added to the css file and looks like:Application
{
font-family: "Myriad Web";
font-size: 12;
}
{
font-family: "Myriad Web";
font-size: 12;
}
To use these styles we add a new tag to our main mxml file. The tag is
<mx:Style> and we simply set the source property to our css file. The new tag will go right underneath the opening application tag and will enable the example to use the new Application style.<mx:Style source="/assets/app.css"/>
Styling the datagrid is going to be done in the same fashion. Now we will setup a "DataGrid" style in which we remove the vertical grid lines and border. Along with these we also set some colors of the selected row, the rolled over row, and the alternating row colors. This is all pretty self explanatory so I won't go into any more detail. The following code goes into our css file.
DataGrid
{
vertical-grid-lines: false;
border-style: none;
selection-color: #C1FFC5;
roll-over-color: #7CFF77;
alternating-item-colors: #F4FBFF, #FFFFFF;
}
{
vertical-grid-lines: false;
border-style: none;
selection-color: #C1FFC5;
roll-over-color: #7CFF77;
alternating-item-colors: #F4FBFF, #FFFFFF;
}
This takes care of updating the style of our datagrid. The last item we are going to play with is the vertical scroll bar. We can style
VScrollBar to modify all the application's vertical scroll bars. Using some images I created for the up (upArrow.png) and down (downArrow.png) arrows and the scroll bar (thumb.png) and scroll background (scrolltrack.png) I can skin what the scroll bar looks like. All these images are included in the "assets" folder in the zip file.We set each of the needed skin styles to our new images. Each piece except the scroll background has an up, over, and down skin but I set all three to the same image for simplicity sake. For the thumb image I used scale-9 to define edge scales, more info on this can be found here. That isn't all that's important though. Remember to use the
Embed tag to embed the image into our application. The style ends up looking like the following.VScrollBar {
downArrowUpSkin:
Embed(source="/assets/downArrow.png");
downArrowOverSkin:
Embed(source="/assets/downArrow.png");
downArrowDownSkin:
Embed(source="/assets/downArrow.png");
upArrowUpSkin:
Embed(source="/assets/upArrow.png");
upArrowOverSkin:
Embed(source="/assets/upArrow.png");
upArrowDownSkin:
Embed(source="/assets/upArrow.png");
thumbDownSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbUpSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbOverSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
trackSkin:
Embed(source="/assets/scrolltrack.png",
scaleGridLeft="7", scaleGridTop="4",
scaleGridRight="8", scaleGridBottom="6");
}
downArrowUpSkin:
Embed(source="/assets/downArrow.png");
downArrowOverSkin:
Embed(source="/assets/downArrow.png");
downArrowDownSkin:
Embed(source="/assets/downArrow.png");
upArrowUpSkin:
Embed(source="/assets/upArrow.png");
upArrowOverSkin:
Embed(source="/assets/upArrow.png");
upArrowDownSkin:
Embed(source="/assets/upArrow.png");
thumbDownSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbUpSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbOverSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
trackSkin:
Embed(source="/assets/scrolltrack.png",
scaleGridLeft="7", scaleGridTop="4",
scaleGridRight="8", scaleGridBottom="6");
}
I know that was a real quick intro into styling and skinning in Flex using css. It should be enough to get you started when customizing the look and feel of your own applications. You can find more information about skinning here.
Final Source Code
Well all that is left is to show you all the final code we end up with.
CSS Code:
/* CSS file */
Application
{
font-family: "Myriad Web";
font-size: 12;
}
DataGrid
{
vertical-grid-lines: false;
border-style: none;
selection-color: #C1FFC5;
roll-over-color: #7CFF77;
alternating-item-colors: #F4FBFF, #FFFFFF;
}
VScrollBar {
downArrowUpSkin:
Embed(source="/assets/downArrow.png");
downArrowOverSkin:
Embed(source="/assets/downArrow.png");
downArrowDownSkin:
Embed(source="/assets/downArrow.png");
upArrowUpSkin:
Embed(source="/assets/upArrow.png");
upArrowOverSkin:
Embed(source="/assets/upArrow.png");
upArrowDownSkin:
Embed(source="/assets/upArrow.png");
thumbDownSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbUpSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbOverSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
trackSkin:
Embed(source="/assets/scrolltrack.png",
scaleGridLeft="7", scaleGridTop="4",
scaleGridRight="8", scaleGridBottom="6");
}
/** Font Info **/
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontWeight: bold;
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontStyle: italic;
}
Application
{
font-family: "Myriad Web";
font-size: 12;
}
DataGrid
{
vertical-grid-lines: false;
border-style: none;
selection-color: #C1FFC5;
roll-over-color: #7CFF77;
alternating-item-colors: #F4FBFF, #FFFFFF;
}
VScrollBar {
downArrowUpSkin:
Embed(source="/assets/downArrow.png");
downArrowOverSkin:
Embed(source="/assets/downArrow.png");
downArrowDownSkin:
Embed(source="/assets/downArrow.png");
upArrowUpSkin:
Embed(source="/assets/upArrow.png");
upArrowOverSkin:
Embed(source="/assets/upArrow.png");
upArrowDownSkin:
Embed(source="/assets/upArrow.png");
thumbDownSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbUpSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
thumbOverSkin:
Embed(source="/assets/thumb.png",
scaleGridLeft="7", scaleGridTop="5",
scaleGridRight="8", scaleGridBottom="7");
trackSkin:
Embed(source="/assets/scrolltrack.png",
scaleGridLeft="7", scaleGridTop="4",
scaleGridRight="8", scaleGridBottom="6");
}
/** Font Info **/
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontWeight: bold;
}
@font-face
{
src:url("/assets/fonts.swf");
fontFamily: "Myriad Web";
fontStyle: italic;
}
The main mxml file.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="530" height="610"
viewSourceURL="/files/AdvancedDatagrid.mxml">
<mx:Style source="/assets/app.css"/>
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
private function displayPersonInfo(item:Object,
col:DataGridColumn):String
{
return item.info.age + " " + item.info.sex;
}
]]>
</mx:Script>
<mx:Model id="people" source="/data/people.xml"/>
<mx:XML id="games" source="/data/games.xml"/>
<mx:Panel width="530" height="610" layout="absolute"
title="Advanced Datagrids">
<mx:Label horizontalCenter="0" y="1"
text="Our Favorite Games"
fontSize="16" fontWeight="bold"/>
<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}"
showHeaders="false">
<mx:columns>
<mx:DataGridColumn headerText="Name" width="75">
<mx:itemRenderer>
<mx:Component>
<mx:VBox verticalGap="2">
<mx:Label text="{data.name.first}" />
<mx:Label text="{data.name.last}" />
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Info" width="80"
labelFunction="displayPersonInfo"/>
<mx:DataGridColumn headerText="Favorite Game"
itemRenderer="comp.ImageRenderer"/>
</mx:columns>
</mx:DataGrid>
<mx:Image x="10" y="318" width="300" height="240"
id="imgGameScreen"
source=
"{games.game.(@id ==
dgPeeps.selectedItem.favGameID).imageURL}"/>
<mx:Label x="10" y="293"
fontWeight="bold" fontSize="13" id="lblGameName"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).name}"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).developer}"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).publisher}"/>
</mx:Panel>
</mx:Application>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="530" height="610"
viewSourceURL="/files/AdvancedDatagrid.mxml">
<mx:Style source="/assets/app.css"/>
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
private function displayPersonInfo(item:Object,
col:DataGridColumn):String
{
return item.info.age + " " + item.info.sex;
}
]]>
</mx:Script>
<mx:Model id="people" source="/data/people.xml"/>
<mx:XML id="games" source="/data/games.xml"/>
<mx:Panel width="530" height="610" layout="absolute"
title="Advanced Datagrids">
<mx:Label horizontalCenter="0" y="1"
text="Our Favorite Games"
fontSize="16" fontWeight="bold"/>
<mx:DataGrid id="dgPeeps" x="0" y="25"
width="510" height="260" selectedIndex="0"
dataProvider="{people.person}"
showHeaders="false">
<mx:columns>
<mx:DataGridColumn headerText="Name" width="75">
<mx:itemRenderer>
<mx:Component>
<mx:VBox verticalGap="2">
<mx:Label text="{data.name.first}" />
<mx:Label text="{data.name.last}" />
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Info" width="80"
labelFunction="displayPersonInfo"/>
<mx:DataGridColumn headerText="Favorite Game"
itemRenderer="comp.ImageRenderer"/>
</mx:columns>
</mx:DataGrid>
<mx:Image x="10" y="318" width="300" height="240"
id="imgGameScreen"
source=
"{games.game.(@id ==
dgPeeps.selectedItem.favGameID).imageURL}"/>
<mx:Label x="10" y="293"
fontWeight="bold" fontSize="13" id="lblGameName"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).name}"/>
<mx:Label x="318" y="318" text="Developer:"/>
<mx:Label x="318" y="335" id="lblDeveloper"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).developer}"/>
<mx:Label x="318" y="361" text="Publisher:"/>
<mx:Label x="318" y="378" id="lblPublisher"
text="{games.game.(@id ==
dgPeeps.selectedItem.favGameID).publisher}"/>
</mx:Panel>
</mx:Application>
Well I hope that this tutorial is useful for many different things. If you have any questions about anything please drop a comment and I will try and get back as fast a possible.
As promissed the .zip file (click me for .zip).
Posted in Flex, All Tutorials by The Fattest |

September 6th, 2007 at 5:48 am
thanks for sharing the source code, i really need it
September 6th, 2007 at 1:52 pm
This was an awesome example. Helped out a lot on my current project. Thanks
September 13th, 2007 at 5:54 am
Nice tut! Helped me out with various projects!
September 19th, 2007 at 8:36 am
I think this tutorial is very helpful. It is very clear and simple. I would just want to know how do you send information from flex to the database?
Thank you!
September 19th, 2007 at 1:52 pm
Check out the other tutorial on flex, php, and mysql I wrote up. If you are looking for something different than that let me know.
September 23rd, 2007 at 12:23 am
I am using custom item renderers. What is the correct way to have the DataGrid CSS directives (such as selection-color) apply to the custom item renderers ? Thanks!
November 5th, 2007 at 6:14 am
Hi,
Nice example, thanks. I tried modifying your code.
I wanted the ability to update the XML (Developer’s name let’s say) so I changed ‘lblDeveloper’ to be a text input.
I also created a button, when clicked, it calls saveData() which is Given Below
Now this is working fine in my flex builder, but when I try to export it, it’s not reading data from the XML file, but using the data I used initially to build it.
I am sure that I am doing something wrong, but what is it? Can you point me to the right direction.
private function saveData():void{
games.game.(@id == dgPeeps.selectedItem.favGameID).developer = lblDeveloper.text
var file:File = File.applicationResourceDirectory.resolvePath(DBPath);
mx.controls.Alert.show(file.nativePath);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeUTFBytes(games.toXMLString());
fileStream.close();
}
Thanks
November 5th, 2007 at 7:12 am
How come when I export this application, the xml files games.xml, and people.xml don’t get exported?
Thanks in Advance
November 11th, 2007 at 11:05 pm
Please answer my Question.
Thanks
November 11th, 2007 at 11:56 pm
So are you exporting a release version? Also the files won’t be embedded into the application.
Charlie
December 11th, 2007 at 10:42 pm
I am making a calendar display and want to show all events for a given day in a datagrid cell. I have included a sample of my XML and my data grid code. Any idea how I can show multiple records in one data grid cell (for example I have a boys event and a girls event scheduled for Dec 12)?
December 9
2007-12-09
10
2007-12-10
11
2007-12-11
12
2007-12-12
18:45:00
6:45 Boys Program
12
2007-12-12
6:45 Girls Program
December 11th, 2007 at 10:51 pm
Tedd,
You could do this by writing your own item renderer and then in the objects in your data provider you could have one variable that could be an array of events. Then in the item renderer you could then loop through the events for the given day. So basically the objects in the dataprovider represent each day and each day has events. Does this make any sense?
December 12th, 2007 at 12:11 pm
It makes perfect sense, I have actually started to do that. I will let you know how it comes out…
December 13th, 2007 at 5:30 pm
Is there any particular reason that this application doesn’t need to override the ’set data’ method in the renderer??
December 13th, 2007 at 5:58 pm
BMW, it doesn’t need to override it because there is no reason to in this case. The data gets set by the datagrid on the renderer and we don’t need to modify it or anything special so we can just use it as it comes in. Now if you wanted to change something like the background color of the item renderer depending on the data you would then need to override the set data method. But if you are using the data as is there is no reason to.
December 16th, 2007 at 10:37 am
thanks a lot for this valuable example!
I just face one problem that clicking the scroll bar area for page down/up doesn’t work. Is there a solution for that?
Regards,
Gennady
January 5th, 2008 at 8:01 am
This code helped me a lot in understanding the xml binding with data grid.
thanks for sharing the code
thanks a lot
January 8th, 2008 at 5:32 am
Thanks a lot. This is really nice example.
January 24th, 2008 at 2:49 pm
Thanks for the explanation fattest
January 30th, 2008 at 5:47 pm
Very nice example. Do you know how can I put a image as background for the list ? Do I have to do implement a special render for the datagrid background ? I intent to build something like itune Artwork in flex do to a slide show - any hint are appreciated!
Q
March 13th, 2008 at 3:49 am
In {data.name.first}, where is data defined or what does it refer to?
Thanks
March 13th, 2008 at 9:13 am
This refers to the data in the item renderer that is always set by the DataGrid, check out this tutorial on item renderers to help explain in a little more detail how this works. But basically data is the object passed to the item renderer and then we can pull out the first name by digging down though the object.
March 13th, 2008 at 12:52 pm
NO .FLA IN THE ZIP????
March 13th, 2008 at 12:57 pm
Me, Flex does not use .fla files. This is not flash. The files compile with the Flex SDK to .swf file. If you’re talking about the fonts I got the swf from Adobe to use.
March 20th, 2008 at 6:54 pm
Wow, thanks for sharing!!!
April 1st, 2008 at 7:40 am
Thanks for a short and simple tute , can we customize a complete column in a datagrid ,
i mean all the rows under a single column, i m trying to do that but unable to find any solution
wud some one pls help me!!
I ll appreciate ur Help
regards,
Lisa
April 1st, 2008 at 8:25 am
Lisa, Yeah sure we can, what are trying to customize about the column? Maybe I can help with a quick solution.
April 1st, 2008 at 8:56 am
hey thanks fat
am actually trying to make the first column a customised row where in just like in MS office excel
i was able to customize the column header but not the first column or rather the vertical row
can u help me on this pls
if u have a solution can u mail me to lisamargret@yahoo.com
regards,
Lisa
April 1st, 2008 at 9:13 am
Lisa, have you tried a custom item renderer in the column, ignoring the data that is coming in? If you are looking for something like excel I think this would handle it nicely. Let me know if you want an example I will write something up real quick.
April 1st, 2008 at 11:52 am
Hey thanks,
i didn’t try item renderer but i would really appreciate an example about it.
Thanks a Ton,
Regards,
Lisa.
April 16th, 2008 at 6:53 am
Hi,
Can any buddy help me in drag n drop. I want to drag cell’s info from 1st datagrid to marge/replace in a row in another datagrid cell.
April 24th, 2008 at 10:56 am
Really helpful. Thank you very much!!
April 30th, 2008 at 10:46 am
@Lisa - if you just want to change the header for a column (like make it bold or include an image), in the DataGridColumn tag, use the property for headerRenderer or headerStyleName
June 10th, 2008 at 1:30 am
Hi,
I have a requirement which is as follows:
“Initially bind first 10 records from 5000 records to the datagrid. On scrolling the scrollbar i need to bind another set of records and so on. Scrolling should be done on both upwards and downwards. i.e. when we go upwards we need to get previous set of records and downwards we need to get next set of records. Another requirement is I need to implement Server-Side Sorting on datagrid”.
Can anyone help me in doing so?.
Thanks in advance…
June 13th, 2008 at 1:19 am
I waant to disply the data in datagrid as a link.How can i do that
June 19th, 2008 at 5:54 am
Hi,
How can i change the header color of the sorted column?
Thanks in advance
June 26th, 2008 at 7:05 pm
Thanks for the detailed example
June 30th, 2008 at 5:20 pm
Thanks for the example.
July 13th, 2008 at 5:19 am
I’m eating this up! Can anyone give me this example with a mx:httpservice url=data.xml example? I have a need to dynamicly update the xml files.
If I understand things correctly, only the httpservice allows you to do that. Either that or you have to recompile every time you get an update.
Such an awesome tutorial!
July 17th, 2008 at 8:11 pm
i am trying to display the numbers form 1 to 75 with a color and 76 to 100 with another color. could any one of u tell me how to do it in flex.
July 23rd, 2008 at 11:35 am
srinu, do mean the rows with that data or the single cell with that data?
Joe you are correct you need to use a httpservice to do this. I will have this in a tutorial here soon.
Rasmi, I assume you figured out how to do this but I will have this in a tutorial also very soon.
July 30th, 2008 at 2:08 am
Really helpful!! The way you’ve explained the entire concept is amazing. Wonderful effort!!
July 30th, 2008 at 10:13 am
Ok here is a new tutorial with the some new datagrid features.
August 12th, 2008 at 1:54 am
Hello guys…
do anyone have any idea of how can i populate and check the text when I add to ADG or DG?
I mean i want to add data to Datagrid in the mean time, i also want to check the input text.
Example…if the data is a specific text like “Online”, I will display an icon/image next to it to indicate this person is online. if “offline”, i will display another image.
so, my problem is can i check like that?
If yes, can u guys guide me, please….
I need ur hlep.
Thanks
August 12th, 2008 at 12:14 pm
scsfdev, yeah I don’t think this would be hard, just create an item renderer that checks the data when set and show the icon with the data is appropriate. let me know if you need more info.
August 17th, 2008 at 9:31 am
I just got it and thanks ‘The Fattest’
Like the way you said, I used Render and check the status and indicate the current status.
thanks
August 18th, 2008 at 4:59 pm
I have searched for a very long time on a way to set a working rotation on the text in a datagrid header at an angle other than +90. I often work with data with large numbers of columns, a descriptive header of some sort, with each cell below containing single character data. Doing this with flex has been far less straightforward to a beginner like me than I had thought it would be.
Originally I had thought it would be really cool to create column headers slanted at 45 deg like you can do with ms excel, overlapping their narrow columns below. Now I’d be happy with a column header that could render the text (embedded is what I’ve been trying) at -90deg, writing up from the bottom of the header cell. 90deg is the only angle which sort of works though it writes down from the top of cell to bottom. This solution uses a VBox holding a label with rotation=”90″ as the headerRenderer.
Maybe this is obvious to experienced folks but I’ve seen a lot of people trying to find how to do this and having trouble finding working solutions.
September 4th, 2008 at 10:07 am
We have been tring to print a Flex3 datagrid landscape for several days ($3,000) and gave up… the product does not seem to lend itself to printing datagrids rotated without and MASSIVE amount of programming that is NOT worth the effort. We ended up pushing the grid results to PHP and printing. GOOD LUCK!