Document directory
- Use Renderer cyclically
- Inline itemrenderer
- Data Grid
- Outerdocument
- Bubble event
- Conclusion
Flex provides many controls that can display large amounts of data in different ways. List controls itself, DataGrid, Tree, and visual classes including charts and AdvancedDataGrid. By default, the Flex list control displays the provided data as simple text. However, Flex is far more capable than this. List Control provides a method to customize its content using itemRenderer. By allowing you to use itemRenderer to fully control the content of each row (or cell) in the list, Flex enables you to compile more eye-catching, creative, and practical applications.
This series discusses Flex itemRenderer and how to use them efficiently and effectively. The first part of this series focuses on inline itemRenderer, which is written into the MXML tag that describes List control. Later articles will discuss the more complex itemRenderer that uses MXML and ActionScript.
Use Renderer cyclically
People often try to access itemRenderer from outside the list. For example, since you have just received new data from the server, you may want to change the fourth column of the fifth row in the DataGrid to green. Retrieving the itemRenderer instance and modifying it externally is a big project for the Flex framework and component model.
To understand itemRenderer, you must understand why they become so and what we designed them. Here, when I use "we", I am referring to the Adobe Flex design team. I have nothing to do with it. If you want to display 1,000 records. If you think the list control will create 1,000 itemRenderer, you will be wrong. If the list shows only 10 rows, it will create about 12 itemRenderer-these are enough to show each visible row, and several more are used for buffering and performance. The List displays rows 1-10. When the user scrolls this list, it may now display rows 3-12. However, the 12 itemrenderers are still there: after the list is rolled in time, no itemRenderer is created.
The following operations are performed by Flex. When the list is rolled, itemRenderer that still displays the same data (Row 3-10) will move up. They did not change, but moved to a new location. The itemRenderer that previously showed Row 1 and row 2 is now moved to itemRendere of Row 10. Then, the itemRenderer provides data for row 11 and row 12. In other words, unless you resize the list, the same itemRenderer will be reused/recycled-they are only moved to a new location and new data is now displayed.
This line of Flex makes the situation more complex in a specific programming environment. For example, if you want to change the background color of a cell in the fourth column of the fifth row, note that if you scroll through the list, the itemRenderer of the cell may now display the content of row 21st.
So how to make such changes?
ItemRenderer must change itself based on the data displayed for them. If the itemRenderer of the list needs to change its color based on the data value, it must view the obtained data and change itself.
Inline itemRenderer
I use the inline itemRenderer in this article to explain how to solve this problem. Inline itemRenderer is directly written to the MXML file to control the position where the message appears. In the next article, I will explain how to write an external itemRenderer. Inline itemRenderer is the simplest and generally used for simple Renderer or prototyping for large applications. Inline itemRenderer is not a problem, but as the Code becomes more complex, it is best to extract it into your own class.
I will use the same data in all examples: a set of book-related information-author, title, publication date, and thumbnail images. Each record is an XML code, as shown below:
<book> <author>Peter F. Hamilton</author> <title>Pandora's Star</title> <image>assets/pandoras_star_.jpg</image><date>Dec 3, 2004</date></book>
I will use<mx:List>
Start with a simple itemRenderer. The author is listed here, followed by the title.
<mx:List x="29" y="67" dataProvider="{testData.book}" width="286" height="190"> <mx:itemRenderer> <mx:Component> <mx:Label text="{data.author}: {data.title}" /> </mx:Component> </mx:itemRenderer></mx:List>
This itemRenderer is too simple and may be better able to use labelFunction, but it allows you to focus at least on the important part. First, use the inline itemRenderer<mx:itemRenderer>
Mark to define it. This tag contains<mx:Component>
Mark. This markRequiredPut it here because it will tell the Flex compiler that you are defining a component inline. I will immediately explain what this means.
You have<mx:Component>
Define itemRenderer in tag. In this example, it is<mx:Label>
And the text field is set to a data binding expression:{data.author}: {data.title}
.This is important.List control by setting the itemRendererdata
Attribute to provide dataProvider records for each itemRenderer instance. For the above Code, it means that for any given list row, the inline itemRenderer instance willdata
Set property<book>
XML nodes (such as the preceding nodes ). When you scroll the list,data
The attribute is also changed because itemRenderer is cyclically used for new rows.
In other words, the itemrenderer instance of Row 1 may nowdata.author
It is set to "Peter F. Hamilton", but when it gets out of the view, itemrenderer is used cyclically and (this itemrenderer)data
Attributes may now includedata.author
Set to "J. K. Rowling ". This is all done automatically when the list is rolled-you don't have to worry about it.
The following is a complex inline itemrenderer.<mx:List>
Control:
<mx:List x="372" y="67" width="351" height="190" variableRowHeight="true" dataProvider="{testData.book}"> <mx:itemRenderer> <mx:Component> <mx:HBox > <mx:Image source="{data.image}" width="50" height="50" scaleContent="true" /> <mx:Label text="{data.author}" width="125" /> <mx:Text text="{data.title}" width="100%" /> </mx:HBox> </mx:Component> </mx:itemRenderer></mx:List>
The difference is not big. This time is not<mx:Label>
, Itemrenderer is<mx:HBox>
And include<mx:Image>
,<mx:Label>
And<mx:Text>
Control. Data Binding will still be visible and associated with records.
Data Grid
You can also use the inline itemrenderer for the DataGrid. The following is an example of a column:
<mx:DataGrid x="29" y="303" width="694" height="190" dataProvider="{testData.book}" variableRowHeight="true"> <mx:columns> <mx:DataGridColumn headerText="Pub Date" dataField="date" width="85" /> <mx:DataGridColumn headerText="Author" dataField="author" width="125"/> <mx:DataGridColumn headerText="Title" dataField="title"> <mx:itemRenderer> <mx:Component> <mx:HBox paddingLeft="2"> <mx:Script> <![CDATA[ override public function set data( value:Object ) : void { super.data = value; var today:Number = (new Date()).time; var pubDate:Number = Date.parse(data.date); if( pubDate > today ) setStyle("backgroundColor",0xff99ff); else setStyle("backgroundColor",0xffffff); } ]]> </mx:Script> <mx:Image source="{data.image}" width="50" height="50" scaleContent="true" /> <mx:Text width="100%" text="{data.title}" /> </mx:HBox> </mx:Component> </mx:itemRenderer> </mx:DataGridColumn> </mx:columns></mx:DataGrid>
As you can see, this time is much more complex than the first two, but with the same structure:<mx:itemRenderer>
Contains<mx:Component>
Definition.
<mx:Component>
To provide an mxml syntax for creating an ActionScript class in code. Imagine cutting<mx:Component>
The code that appears in the block, put it into a separate file, and provide a class name. When you view the inline itemrenderer, it looks like a complete mxml file, isn't it? Root flag (in this example<mx:HBox>
), Or even<mx:Script>
Block.
In this example<mx:Script>
Blocks are used to override the Set Data function, so that the background color of itemrenderer can be changed. In this example, the background will change from white to other colors no matter when the book's future data is published.Remember, itemrenderer is used cyclically, so if the test fails, you must set the color back to white. Otherwise, when the user scrolls the list, all itemrenderer will eventually change to purple.
OuterDocument
ScopeAlso changed. I mean, from<mx:Component>
The variables defined in only apply to that component/inline itemrenderer. Similarly,<mx:Component>
The external content is in different scopes, as this component is defined in another file. For example, if you add a button for this itemrenderer, you can buy books from online retailers. The buttons call theirclick
So you can define this button as follows:
<mx:Button label="Buy" click="buyBook(data)" />
If<mx:Script>
Block DefinitionbuyBook()
Function, an error is displayed, indicatingbuyBook()
Is an undefined method. This is becausebuyBook()
Is within the scope of the file, not in<mx:Component>
. This is a typical use case.outerDocument
Identifiers can avoid this problem:
<mx:Button label="Buy" click="outerDocument.buyBook(data)" />
outerDocument
The identifier changes the scope of action to search for files or external documents and references<mx:Component>
. Note: This function must be a public function, not a protected or private function. Remember,<mx:Component>
Class defined externally.
Bubble event
Now let's look at another more complex example. This is a tilelist that uses the same data.
<mx:TileList x="29" y="542" width="694"dataProvider="{testData.book}" height="232" columnWidth="275"rowHeight="135" > <mx:itemRenderer> <mx:Component> <mx:HBox verticalAlign="top"> <mx:Image source="{data.image}" /> <mx:VBox height="115" verticalAlign="top" verticalGap="0"> <mx:Text text="{data.title}" fontWeight="bold" width="100%"/> <mx:Spacer height="20" /> <mx:Label text="{data.author}" /> <mx:Label text="Available {data.date}" /> <mx:Spacer height="100%" /> <mx:HBox width="100%" horizontalAlign="right"> <mx:Button label="Buy" fillColors="[0×99ff99,0×99ff99]"> <mx:click> <mx:Script> <![CDATA[ var e:BuyBookEvent = new BuyBookEvent(); e.bookData = data; dispatchEvent(e); ]]> </mx:Script> </mx:click> </mx:Button> </mx:HBox> </mx:VBox> </mx:HBox> </mx:Component> </mx:itemRenderer></mx:TileList>
Implement an itemrenderer in tilelist.
The itemrenderer is very similar to the one used in the DataGrid, butclick
Events are not usedouterDocument
Call a function. In this example,click
Event creates a Custom Event, which uses tilelistRiskAnd received by higher components in the visual chain.
This is a very common problem: You have an itemrenderer, which contains some interactive controls, usually buttons, linkbuttons, or other components that will cause specific actions when you click. It may be to delete a row or purchase a book in this example.
It is not reasonable to expect itemrenderer to complete the job. After all, itemrenderer is only responsible for making the list look beautiful. The event bubbling allows the itemrenderer to transfer the task to another person. The Custom Event comes in handy at this time because it is related to the data in the row. Why not include the data in the event? In this case, the event receiver does not have to search for it.
Conclusion
Using inline itemrenderer is a good way to quickly customize the appearance of a list. Consider using the inline itemrenderer as a separate ActionScript class-they are, after all, just as there is a range of effects. You can useouterDocument
Identifier change scope of action. If you want to transmit information based on the interaction result with itemrenderer, you can use a custom bubble event.
Remember:Do not try to catch the itemrenderer without placing it-they will be used cyclically. They are only responsible for processing the received data.