Flex 内联渲染器(下)

数据网格

也可以将内联 itemRenderer 用于 DataGrid。以下是应用于列的一个示例:

Xml代码
  1. < mx:DataGrid   x = "29"   y = "303"   width = "694"   height = "190"   dataProvider = "{testData.book}"   variableRowHeight = "true" >   
  2.     < mx:columns >   
  3.         < mx:DataGridColumn   headerText = "Pub Date"   dataField = "date"   width = "85"   />   
  4.         < mx:DataGridColumn   headerText = "Author"   dataField = "author"   width = "125" />   
  5.         < mx:DataGridColumn   headerText = "Title"   dataField = "title" >   
  6.             < mx:itemRenderer >   
  7.                 < mx:Component >   
  8.                     < mx:HBox   paddingLeft = "2" >   
  9.                         < mx:Script >   
  10.                         <![CDATA[  
  11.                             override public function set data( value:Object ) : void {  
  12.                                 super.data = value;  
  13.                                 var today:Number = (new Date()).time;  
  14.                                 var pubDate:Number = Date.parse(data.date);  
  15.                                 if( pubDate > today ) setStyle("backgroundColor",0xff99ff);  
  16.                                 else setStyle("backgroundColor",0xffffff);  
  17.                             }  
  18.                         ]]>   
  19.                         </ mx:Script >   
  20.                         < mx:Image   source = "{data.image}"   width = "50"   height = "50"   scaleContent = "true"   />   
  21.                         < mx:Text   width = "100%"   text = "{data.title}"   />   
  22.                     </ mx:HBox >   
  23.                 </ mx:Component >   
  24.             </ mx:itemRenderer >   
  25.         </ mx:DataGridColumn >   
  26.     </ mx:columns >   
  27. </ mx:DataGrid >   
<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>

 

如您所见, 这次比前两个要复杂得多, 但结构相同: <mx:itemRenderer> 包含一个 <mx:Component> 定义。

<mx:Component> 是为了提供一个 MXML 语法, 用于在代码中创建一个 ActionScript 类。想象一下, 剪切 <mx:Component> 块中出现的代码并将它放入一个单独文件中并提供一个类名称。当您查看内联 itemRenderer 时, 它看上去就像一个完整的 MXML 文件, 不是吗?有根标记 (本例中为 <mx:HBox> ), 甚至 <mx:Script> 块。

本例中的 <mx:Script> 块用于覆盖 set data 函数, 使得 itemRenderer 的背景色可以更改。在本例中, 无论书籍的未来出版数据为何时, 背景将从白色更改为其他颜色。记住, itemRenderer 是循环使用的, 所以如果测试失败, 还必须将颜色设置回白色。否则, 当用户滚动列表时, 所有 itemRenderer 最终将变为紫色。

outerDocument

scope 也更改了。我的意思是, 从 <mx:Component> 中定义的变量仅作用于那个组件/内联 itemRenderer。同样, <mx:Component> 外的内容在不同的作用范围内, 就像这个组件是在另一个文件中定义的那样。例如, 假设您为这个 itemRenderer 添加了一个 Button, 允许用户从在线零售商那里购买书籍。Button 调用它们的 click 事件上的函数, 所以您可以如下定义这个按钮:

Java代码
  1. <mx:Button label= "Buy"  click= "buyBook(data)"  />  
<mx:Button label="Buy" click="buyBook(data)" />

 

如果在文件的 <mx:Script> 块中定义 buyBook() 函数, 会显示一个错误, 指出 buyBook() 是一个未定义的方法。这是因为 buyBook() 是在文件的作用范围内而不是在 <mx:Component> 的作用范围内定义的。由于这是一个典型用例, 使用 outerDocument 标识符可以避开这个问题:

Xml代码
  1. < mx:Button   label = "Buy"   click = "outerDocument.buyBook(data)"   />   
<mx:Button label="Buy" click="outerDocument.buyBook(data)" />

 

outerDocument 标识符将作用范围更改为查找文件或外部文档, 并引用 <mx:Component> 。现在请注意: 这个函数必须是公共函数, 而不是受保护或私有函数。记住, <mx:Component> 被视为外部定义的类。

冒泡事件

现在我们来看另一个更复杂的示例。这是一个使用相同数据的 TileList。

Xml代码
  1. < mx:TileList   x = "29"   y = "542"   width = "694"   
  2. dataProvider = "{testData.book}"   height = "232"   columnWidth = "275"   
  3. rowHeight = "135"   >   
  4.     < mx:itemRenderer >   
  5.         < mx:Component >   
  6.             < mx:HBox   verticalAlign = "top" >   
  7.                 < mx:Image   source = "{data.image}"   />   
  8.                 < mx:VBox   height = "115"   verticalAlign = "top"   verticalGap = "0" >   
  9.                     < mx:Text   text = "{data.title}"   fontWeight = "bold"   width = "100%" />   
  10.                     < mx:Spacer   height = "20"   />   
  11.                     < mx:Label   text = "{data.author}"   />   
  12.                     < mx:Label   text = "Available {data.date}"   />   
  13.                     < mx:Spacer   height = "100%"   />   
  14.                     < mx:HBox   width = "100%"   horizontalAlign = "right" >   
  15.                         < mx:Button   label = "Buy"   fillColors = "[0×99ff99,0×99ff99]" >   
  16.                            < mx:click >   
  17.                            < mx:Script >   
  18.                             <![CDATA[  
  19.                                 var e:BuyBookEvent = new BuyBookEvent();  
  20.                                 e.bookData = data;  
  21.                                 dispatchEvent(e);  
  22.                             ]]>   
  23.                             </ mx:Script >   
  24.                             </ mx:click >   
  25.                         </ mx:Button >   
  26.                     </ mx:HBox >   
  27.                 </ mx:VBox >   
  28.             </ mx:HBox >   
  29.         </ mx:Component >   
  30.     </ mx:itemRenderer >   
  31. </ mx:TileList >   
<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>

 

当应用程序运行时, itemRenderer 看上去如图 1:

 

这个 itemRenderer 与 DataGrid 中使用的那个十分相似, 但“购买”按钮的 click 事件不使用 outerDocument 调用函数。在本例中, click 事件会创建一个自定事件, 后者通过 TileList 从 itemRenderer 中 出, 并由可视链中的较高组件接收。

这是一个很常见的问题: 您有一个 itemRenderer, 而它包含一些交互控制, 通常是 Button、LinkButton 或其他单击时会导致发生特定动作的组件。可能是删除行或是本例中的购买书籍。

指望 itemRenderer 完成这个工作并不合理。毕竟, itemRenderer 只负责让列表看上去美观。事件 bubbling 允许 itemRenderer 将这个工作转交给他人。自定事件此时派上了用场, 因为这个事件与行中的数据相关;为何不将数据包含在事件中呢?如果那样, 事件接收方就不必苦苦搜寻它了。

结论

使用内联 itemRenderer 是一种快速自定列表外观的好方法。考虑将内联 itemRenderer 作为单独的 ActionScript 类-它们毕竟像有作用范围一样。如果必须引用包含文件中的函数或属性, 可使用 outerDocument 标识符更改作用范围。如果需要根据与 itemRenderer 的交互结果传达传递信息, 可使用自定冒泡事件。

并且记住: 不要试图抓住 itemRenderer 不放-它们将循环使用。它们只负责处理收到的数据。

我在下一篇文章中将讨论外部 itemRenderer。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值