The host component of the item renderer is called the item
renderer’s owner. The host component passes information to the item
renderer by using the properties defined by the IDataRenderer and
IItemRenderer interfaces.
The data item to render or edit as defined
in the data provider of the host component.
IDataRenderer
dragging
Boolean
Contains true if the item
renderer is being dragged.
Mobile applications do not support
drag and drop. Therefore, for an item renderer used only in a mobile
application, you can define this property with a setter/getter that
always returns false. To use the item renderer
in a desktop application that supports drag and drop, you must implement
it.
IItemRenderer
itemIndex
int
The index of the item in the data provider
of the host component of the item renderer.
IItemRenderer
label
String
A String representation of the data item
to display in the item renderer.
IItemRenderer
selected
Boolean
Contains true if the item
renderer can show itself as selected.
Many Spark components,
such as the DataGroup and SkinnableDataContainers support item renderers,
but do not support the selection of a data item. Other Spark components,.
such as List, ComboBox, and DataGrid, support the selection of a
data item.
IItemRenderer
showsCaret
Boolean
Contains true if the item
renderer can show itself as focused.
IItemRenderer
Your item renderer might also implement the hovered property.
The hovered property is not defined by an interface but is implemented
by many Flex item renderers. The following table describes the hovered property:
Item renderer property
Type
Description
Interface
hovered
Boolean
Contains true when the
user hovers over the list item. Typically, the item renderer listens
for the rollOver and rollOut events
to set hovered and to update the display of the
item renderer accordingly.
Mobile applications do not support
hovered. For an item renderer used in a mobile application, you
are not required to implement the hovered property. To use the item
renderer in a desktop application, you must implement it. The predefined
mobile item renderers supplied with Flex implement the hovered property
so that you can use the item renderer in a mobile and desktop application.
None
The UIComponent class,
the base class for all Flex components including item renderers,
defines the owner property. The owner property
contains a reference to the component that hosts the item renderer.
For example, the SkinnableDataContainer can be the owner of an item
renderer. From within the item renderer, you can access the host
component by using the owner property.
The host component of an item renderer must implement the IItemRendererOwner interface.
That interface defines the following methods to write information
to the item renderer:
Host component method
Description
Interface
itemToLabel()
Converts the data item to a String representation.
Host
components can override this method to customize the String conversion.
IItemRendererOwner
updateRenderer()
Write the data item as a String to the label property.
Updates the owner property with a reference to
the host component. The last thing this method does is set the data property
of the item renderer.
Host components can override this method
to write additional information to the item renderer.
IItemRendererOwner
Before you create a custom item renderer, decide how to pass
the data item to the item renderer. In some situations, you want
the host component to perform any processing on the data item before
it passes it to the item renderer. If so, override the itemToLabel() and updateRenderer() methods
in the host component. The item renderer then accesses the data
by using the label property.
Instead of the host component processing the data item, the item
renderer can perform the processing. If you want the item renderer
to process the data item, use IDataRenderer.data property
to pass it. The item renderer then accesses the data property
and performs any processing on the data item before displaying it.
Passing data using the IItemRenderer.label property
If the data item is a String, or a value that can easily
be converted to a String, you can use the IItemRenderer.label property
to pass it to the item renderer. If the data item is in a format
that must be converted to a String representation, override the IItemRendererOwner.itemToLabel() method
in the host component to customize the conversion.
The executing SWF file for the previous example is shown below:
This example uses a custom item renderer named MySimpleColorRenderer, defined
in the file MySimpleColorRenderer.mxml, that shows the String text
in a background of the matching color. Shown below is the MXML item
renderer:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleColorRenderer.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
autoDrawBackground="false">
<fx:Script>
<![CDATA[
// Property to hold the RGB color value.
[Bindable]
public var myColor:uint;
// Write String to labelDisplay component.
override public function set label(value:String):void
{
super.label = value;
labelDisplay.text = label;
// Determine the RGB color value from the data item.
if (label == "red")
myColor = 0xFF0000;
if (label == "green")
myColor = 0x00FF00;
if (label == "blue")
myColor = 0x0000FF;
}
]]>
</fx:Script>
<!-- Set the background color to the RGB color value.-->
<s:Rect width="100%" height="100%" alpha="0.5">
<s:fill>
<s:SolidColor color="{myColor}" />
</s:fill>
</s:Rect>
<!-- Display the color name -->
<s:Label id="labelDisplay"/>
</s:ItemRenderer>
In this example, the item renderer overrides the label property
to write the color to the Label control, and set the fill color
of the Rect component.
This item renderer displays the data with no visual changes based
on state. Therefore, it sets the ItemRenderer.autoDrawBackground property
to false. This item renderer is useful for displaying
data in the container when it does not have any user interaction.
For an example of an item renderer that changes its display based
on user interaction, see Controlling the background color using the autoDrawBackground property.
If you want to modify the String passed to the label property,
you can override the itemToLabel() method in the
host component. The itemToLabel() method has the
following signature:
itemToLabel(item:Object):String
The method takes a single argument representing the data item.
It returns a String representation of the data item for display
in the item renderer.
In the following example, each data item is represented by an
Object containing three fields. The custom SkinnableDataContainer
container, called MyDataGroup, overrides the itemToLabel() method
to format the Object as a String before passing the String to the
item renderer. The example then uses the DefaultItemRenderer to
display the text:
The executing SWF file for the previous example is shown below:
The MyDataGroup.mxml file defines the custom SkinnableDataContainer container
that overrides the itemToLabel() method:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MyDataGroup.mxml -->
<s:SkinnableDataContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
// Override to return the Object as a formatted String.
override public function itemToLabel(item:Object):String {
var tempString:String;
if (item == null)
return " ";
tempString = item.firstName + " " + item.lastName
+ " " + ", ID: " + item.companyID;
return tempString;
}
]]>
</fx:Script>
</s:SkinnableDataContainer>
Passing data using the IIDataRenderer.data property
Rather than processing the data in the host component,
you can let the item renderer perform all the processing of the
data item for display. In this situation, use the ItemRenderer.data property
to pass the data item to the item renderer. This technique lets
you define a set of item renderers that display the same data in
different ways depending on your application requirements.
The executing SWF file for the previous example is shown below:
The SkinnableDataContainer uses
a custom item renderer named MySimpleItemRenderer.mxml. The custom
item renderer displays the firstName and lastName fields in a single
Label control, and display the companyID in a second Label control:
The data property contains an Object passed
from the DataGroup container. The
Object represents the data item in its original form. The renderer
uses data binding to populate the controls in the item renderer
from the data property. The two Label controls
are defined in a Group container so that they can be layed out horizontally.
Rather than using data binding, you can override the data property
in the item renderer. Within the override, you can modify the data
or perform other processing, then set properties in the renderer.
The following example shows an alternative implementation of MySimpleItemRenderer.mxml
that overrides the data property:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleItemRendererDataOverride.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
// Check to see if the data property is null.
if (value== null)
return;
// If the data property is not null,
// set the Label controls appropriately.
nameLabel.text = value.firstName + ', ' + value.lastName;
compLabel.text = value.companyID;
}
]]>
</fx:Script>
<s:HGroup verticalCenter="0" left="2" right="2" top="2" bottom="2">
<s:Label id="nameLabel"/>
<s:Label id="compLabel"/>
</s:HGroup>
</s:ItemRenderer>
Controlling the background display of an item renderer
An item renderer controls the background display of the
data item in the host component. Typically, an item renderer changes
the background display of the data item to reflect user interaction.
For example, an item renderer can use a transparent background when
there is no user interaction with the data item. It could draw a
blue background when the data item is selected, and a different background
when the user hovers over the data item.
Flex defines the following CSS styles to define background colors
for the three common user interactions:
Interaction
Style
Value for Spark theme
Value for Mobile theme
none
contentBackgroundColor
0xFFFFFF (white)
0x464646 (dark grey)
hovered
rollOverColor
0xCEDBEF (light blue)
0xCEDBEF (light blue/grey)
selected
selectionColor
0xA8C6EE (dark blue)
0xB2B2B2 (light grey)
These colors are defined in the default.css file for the spark.swc
and mobilecomponents.swc file. If you want your item renderer to
mimic the color setting of Flex, use these same colors for setting
the background color of your custom item renderers.
You can use these same styles in a custom item renderer to mimic
the default background colors used by Flex component. Or, you can
define your item renderers to use different colors and backgrounds.
If you define an MXML item renderer, you typically create it
as a subclass of the ItemRenderer class. The ItemRenderer class
defines the default background color for all types of user interactions.
By default the item renderer draws a transparent background around
the item when there is not user interaction. It draws a light-blue
background around an item when you hover over it. For more information, see Controlling the background color using the autoDrawBackground property.
If you define an item renderer in ActionScript, you define the
background colors of the data item. You can choose to implement
your item renderer to use the predefined CSS styles, or define your
own.
In your main application, you can redefine the CSS styles for
the background colors. The following applications sets the rollOverColor style
of the application to green:
The executing SWF file for the previous example is shown below:
Using an item renderer function with a Spark container
In
some applications, you display different types of data items in
a single container. In this scenario, each type of data item needs
its own item renderer. Or, you mix data items and Flex components
in a container. To mix data items and Flex components, define different
item renderers for the data items and the Flex components.
You can use an item renderer function to examine each data item
to determine which item renderer to use. The DataGroup.itemRendererFunction and SkinnableDataContainer.itemRendererFunction property
takes a function with the following signature:
function itemRendererFunction(item:Object):ClassFactory
Where item is the data item, and the return
value is the item renderer. If the child is a Flex component, return
DefaultComplexItemRenderer to display the child in a Group container.
Alternatively, return null to display the child
with no renderer.
The following example defines an item renderer function to return
one item renderer for data items defined as Object, and another
item renderer for data items defined as String:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\SparkDataGroupContainerFunction.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import myComponents.MySimpleItemRendererFunction;
import spark.skins.spark.DefaultItemRenderer;
private function selectRenderer(item:Object):ClassFactory {
var classFactory:ClassFactory;
if (item is String) {
// If the item is a String, use DefaultItemRenderer.
classFactory = new ClassFactory(DefaultItemRenderer);
}
else {
// If the item is an Object, use MySimpleItemRendererFunction.
classFactory = new ClassFactory(MySimpleItemRendererFunction);
}
return classFactory;
}
]]>
</fx:Script>
<s:DataGroup itemRendererFunction="selectRenderer">
<s:layout>
<s:TileLayout requestedColumnCount="3"/>
</s:layout>
<mx:ArrayList>
<fx:Object firstName="Bill" lastName="Smith" companyID="11233"/>
<fx:String>617-555-1212</fx:String>
<fx:String>Newton</fx:String>
<fx:Object firstName="Dave" lastName="Jones" companyID="13455"/>
<fx:String>617-555-5555</fx:String>
<fx:String>Newton</fx:String>
<fx:Object firstName="Mary" lastName="Davis" companyID="11543"/>
<fx:String>617-555-6666</fx:String>
<fx:String>Newton</fx:String>
</mx:ArrayList>
</s:DataGroup>
</s:Application>
The executing SWF file for the previous example is shown below:
You also use item renderer function when mixing data items and
Flex components in the container. Flex components implement the IVisualElement interface, and
therefore do not need an item renderer to draw them on the screen.
In your item renderer function, you can determine if the data item
corresponds to a Flex component. If so, the item renderer function
returns the DefaultComplexItemRenderer, as the following example
shows:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\SparkDataGroupContainerFunctionVisual.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.core.IVisualElement;
import myComponents.MySimpleItemRendererEmployee;
import spark.skins.spark.DefaultComplexItemRenderer;
private function selectRenderer(item:Object):ClassFactory {
var classFactory:ClassFactory;
if(item is IVisualElement){
// If the item is a Flex component, use DefaultComplexItemRenderer.
classFactory = new ClassFactory(DefaultComplexItemRenderer);
}
else if (item is Object){
// If the item is an Object, use MySimpleItemRendererFunction.
classFactory = new ClassFactory(MySimpleItemRendererEmployee);
}
return classFactory;
}
]]>
</fx:Script>
<s:DataGroup itemRendererFunction="selectRenderer">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:ArrayList>
<fx:Object firstName="Bill" lastName="Smith" companyID="11233"/>
<fx:Object firstName="Dave" lastName="Jones" companyID="13455"/>
<fx:Object firstName="Mary" lastName="Davis" companyID="11543"/>
<fx:Object firstName="Debbie" lastName="Cooper" companyID="14266"/>
<s:Button label="Add Employee"/>
</mx:ArrayList>
</s:DataGroup>
</s:Application>
The executing SWF file for the previous example is shown below:
Spark item renderer precedence
The DataGroup and SkinnableDataContainer containers use
the follow rules to determine the item renderer for a child:
If the itemRendererFunction property
is defined, call the associated function to obtain the item renderer.
If the function returns null, go to rule 2.
If the itemRenderer property is defined,
use the specified item renderer to display the item.
If the item is implements mx.core.IVisualElement and is of
type flash.display.DisplayObject, use it directly.
Dispatch a runtime error if no item renderer found.
Creating a recyclable item renderer for virtual layout
With virtual layout disabled, the DataGroup and SkinnableDataContainer containers
create one instance of the item renderer for each child. With virtual layout
enabled, the container only creates enough item renderers to display
its currently visible children. Virtual layout greatly reduces the
overhead required to use the DataGroup and SkinnableDataContainer
containers.
With virtual layout enabled, when a child is moved off the visible
area of the container, its item renderer is recycled. When the item
renderer is reused, its data property is set to
the data item representing the new child. Therefore, if a recycled
item renderer performs any actions based on the value of the data property,
it must first check that the property is not null.
When the item renderer is reassigned, Flex also calls the updateRenderer() method
of the item renderer owner. This method must set the owner and label properties
on the item renderer. Subclasses of SkinnableDataContainer, can
use the updateRenderer() method to set additional
properties on the item renderer.
Because a container can reuse an item renderer, ensure that you
fully define its state. For example, you use a CheckBox control
in an item renderer to display a true (checked)
or false (unchecked) value based on the current
value of the data property. A common mistake is
to assume that the CheckBox control is always in its default state
of unchecked and only inspect the data property for a value of true.
However, remember that the CheckBox can be recycled and had previously
been checked. Therefore, inspect the data property
for a value of false, and explicitly uncheck the
control if it is checked, as the following example shows:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleItemRendererCB.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
dataChange="setMgr();">
<fx:Script>
<![CDATA[
private function setMgr():void {
// Check to see if the data property is null.
if (data == null)
return;
// If the data property is not null,
// set the CheckBox control appropriately..
if (data.manager == "yes") {
mgr.selected = true;
}
else {
mgr.selected = false;
}
}
]]>
</fx:Script>
<s:HGroup verticalCenter="0" left="2" right="2" top="2" bottom="2">
<s:Label text="{data.lastName}, {data.firstName}"/>
<s:Label text="{data.companyID}"/>
<s:CheckBox id="mgr"/>
</s:HGroup>
</s:ItemRenderer>
Use the dataChange event of the ItemRenderer
class to detect the change to its data property.
This event is dispatched whenever the data property changes.
Alternatively, you can override the data property.
Alternatively, you can override the ItemRenderer.data property
itself, as the following example shows:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleItemRendererCBData.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
// Check to see if the data property is null.
if (value== null)
return;
// If the data property is not null,
// set the CheckBox control appropriately..
if (value.manager == "yes") {
mgr.selected = true;
}
else {
mgr.selected = false;
}
}
]]>
</fx:Script>
<s:HGroup verticalCenter="0" left="2" right="2" top="2" bottom="2">
<s:Label text="{data.lastName}, {data.firstName}"/>
<s:Label text="{data.companyID}"/>
<s:CheckBox id="mgr"/>
</s:HGroup>
</s:ItemRenderer>
Defining a typical item for determining the size of an item renderer
When using virtual layout with the DataGroup and SkinnableDataContainer containers,
you can pass to the container a data item that defines a typical
data item. The container then uses the typical data item, and the
associated item renderer, to determine the default size of the child.
By defining the typical item, the container does not have to size
each child as it is drawn on the screen.
If you do not specify the data item, by default the control uses
the first item in the data provider as the typical data item.
Use the typicalItem property of the container
to specify the data item, as the following example shows:
The executing SWF file for the previous example is shown below:
In this example, you define typicalObj, an Object that represents
a data item with a long value for the firstName and lastName fields.
You then pass typicalObj to the typicalItem property
of the container. The container uses that data item, and the associated
item renderer, to determine the size of the children.
Specifying a value for the typicalItem property
passes that value, and the associated item renderer, to the typicalLayoutElement property
of the layout of the container. For more information on the typicalLayoutElement property,
see Set the row height or column width of a layout.