如果您要显示大量 itemRenderer-无论在 DataGrid 还是在 AdvancedDataGrid 中-如果无法有效编写这些 itemRenderer, 您的应用程序性能可能受到负面影响。以下是一些可能有所帮助的提示:
以下 itemRenderer 根据数据字段的值切换组件。
<mx:Canvas> <mx:Script><![CDATA private function lessThanZero() : Boolean { return data.price < 0; } ]]></mx:Script> <mx:Label text="{data.price}" color="#FF0000" visible="{lessThanZero()}" /> <mx:Label text="{data.price}" color="#00FF00" visible="{!lessThanZero()}" /> </mx:Canvas>
这比设置样式要快。要注意的其他事项包括:
目前编写 itemRenderer 最有效的方式是使用 ActionScript 类扩展 UIComponent。您可以全面控制代码, 并且渲染器也可以尽可能高效。
从上例切换样式开始, 编写一个扩展 UIComponent 的简单 itemRenderer。
package renderers { import mx.controls.listClasses.IListItemRenderer; import mx.core.UIComponent; public class PriceItemRenderer extends UIComponent implements IListItemRenderer { public function PriceItemRenderer() { super(); } } }
您会发现我不仅编写这个类来扩展 UIComponent, 还由它实施 IListItemRenderer 接口。这样做是有必要的, 因为 List 控制将需要任何渲染器实施该接口, 否则您会收到运行时错误, 因为列表尝试将渲染器转换为该接口。
如果阅读 IListItemRenderer 的相关文档, 您会发现这是一个许多其他接口的集合, UIComponent 会为您实施其中的大多数。但有一个 IListItemRenderer 扩展的接口是 UIComponent 不实施的:IDataRenderer。这需要您添加代码, 为 itemRenderer 类提供您一直使用的 data
属性。
如果您尝试不实施 IDataRenderer 就使用这个类, 则编译代码时会收到以下错误:
编辑这个类并将它更改为以下内容:
package renderers { import mx.controls.listClasses.IListItemRenderer; import mx.core.UIComponent; import mx.events.FlexEvent; public class PriceItemRenderer extends UIComponent implements IListItemRenderer { public function PriceItemRenderer() { super(); } // Internal variable for the property value. private var _data:Object; // Make the data property bindable. [Bindable("dataChange")] // Define the getter method. public function get data():Object { return _data; } // Define the setter method, and dispatch an event when the property // changes to support data binding. public function set data(value:Object):void { _data = value; dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE)); } } }
我直接使用 IDataRenderer 的 Flex 文档中的代码, 这样您都不用自己键入它。
移除它后, 您可以加入两个标签。
添加变量用于存放这两个标签。
private var posLabel:Label; private var negLabel:Label;
将 set data
函数修改为调用 invalidateProperties()
。这很重要, 因为更改数据必须更改标签中的文本以及它们的可视性。
public function set data(value:Object):void { _data = value; invalidateProperties(); dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE)); }
调用 invalidateProperties()
会告知 Flex 框架在适当的时间调用 commitProperties() 函数。
覆盖 createChildren()
并创建标签, 添加它们以显示组件列表。注意, 除了创建标签外, 还会设置它们的样式和 visible
属性。
override protected function createChildren() : void { super.createChildren(); posLabel = new Label(); posLabel.visible = false; posLabel.setStyle("color", 0×00FF00); addChild(posLabel); negLabel = new Label(); negLabel.visible = false; negLabel.setStyle("color", 0xFF0000); addChild(negLabel); }
覆盖 commitProperties()
以设置标签的文本和可视性。过去, 您一直通过覆盖 set data
进行这类更改, 如果您喜欢, 也可以在这个类中那样做。
override protected function commitProperties():void { super.commitProperties(); posLabel.text = data.price; negLabel.text = data.price; posLabel.visible = Number(data.price) > 0; negLabel.visible = Number(data.price) < 0; }
覆盖 updateDisplayList()
以设置标签大小并进行定位。您必须设置标签大小, 因为它们的默认大小为 0×0。这是 Container 类将为您做的另一件事。由于这个 itemRenderer 十分简单, 您只需将标签大小设置为与 itemRenderer 大小匹配即可。
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ) : void { super.updateDisplayList(unscaledWidth, unscaledHeight); posLabel.move(0,0); posLabel.setActualSize(unscaledWidth,unscaledHeight); negLabel.move(0,0); negLabel.setActualSize(unscaledWidth, unscaledHeight); }
所有这些只能做到这点似乎有点复杂, 但是请记住一点, 使用容器增加的代码要比这多得多。
UIComponent 类是所有可视 Flex 组件 (控制和容器) 的基础。以下是将 UIComponent 用作 itemRenderer 的一些相关提示。
updateDisplayList()
中指定的大小绘制图形和位置子代。variableRowHeight
, 您还应覆盖 measure()
函数, 告知列表 itemRenderer 有多大。有关 Flex itemRenderer 的系列到此结束。希望您通过这些文章了解到使用 itemRenderer 可以在 Flex 应用程序中做些什么以及如何处理它们的数据、外观和行为的最佳做法。您可以在 Adobe Flex 3 文档*中找到 Flex itemRenderer 的更多相关信息。