原文地址:http://www.adobe.com/cn/devnet/flex/articles/itemrenderers_pt3.html
在本系列的第 2 部分中, 我向您展示瞭如何使用 MXML 和 ActionScript 創建外部 itemRenderer。在我用過的示例中, 有一個調度自定事件 BuyBookEvent 的 Button-這樣應用程序可以對它作出響應。本文進一步討論與 itemRenderer 的通信。
我堅信有一條規則是永遠不能違背的: 不能抓住 itemRenderer 的實例不放, 更改它 (設置公共屬性) 或調用它的公共方法。這對我而言是一個禁忌。itemRenderer 是很難弄清的, 我在第 1 部分中說到了其中的緣由: itemRenderer 是循環使用的。抓住一個會破壞 Flex 框架。
請將這條規則謹記在心, 您可以使用 itemRenderer 完成以下操作:
- itemRenderer 可以通過它的列表所有者調度事件。 (您已經看到過冒泡; 這個做法更好, 接下來您就會看到。)
- itemRenderer 可以使用靜態類成員。其中包括 Application.application。如果您的值“全局”存儲在應用程序對象中, 您可以通過這種方式獲得它們。
- itemRenderer 可以使用擁有它的列表的公共成員。接下來您就會看到。
- itemRenderer 可以使用數據記錄中的任何內容。例如, 記錄中的某個項目不用於直接顯示, 但它卻影響 itemRenderer 的行爲方式。
本系列包含以下文章:
要求
爲了充分利用本文, 您需要以下軟件和文件:
Flex Builder 3
必要條件
要從本文中受益, 您最好熟悉 Flex Builder 和 ActionScript 3.0。
動態更改 itemRenderer
以下是上一篇文章中用於 TileList 的 MXML itemRenderer。我將使它對外部源 (我將這個文件稱爲 BookItemRenderer.mxml) 的更改作出反應, 從而使它更生動:
假設您在 TileList 中顯示一個商品目錄。您還有一個 Slider (不屬於 itemRenderer), 它允許用戶給出一個價格範圍; 在此範圍之外的所有商品應變灰 (itemRenderer 的 alpha 值應改變)。您需要告知所有 itemRenderer 標準已改變, 這樣它們可以修改自己的 alpha 值。
覆蓋 set data 可能如下:
問題是: 如何更改標準
值?itemRenderer 的“最佳做法”是始終讓它們處理爲自己手頭的數據。在本例中, 將測試標準作爲數據的一部分不可能也不切實際。所以這在數據外留下了一個位置。您有兩個選擇:
- 列表本身的一部分。即, 您的列表 (List、DataGrid、TileList 或其他) 可以是擴展列表控制並且將這個標準作爲公共成員的類。
- 作爲全局數據的應用程序的一部分。
我選擇第一個: 擴展一個類並將這個標準作爲該類的一部分。畢竟, 這個類將用於顯示數據, 而標準是顯示內容的一部分。對於本例, 我將擴展 TileList 並將標準作爲公共數據成員。
這個辦法是, itemRenderer 外的控制可以通過更改列表控制上的這個屬性來修改標準。
listData
itemRenderer 可以訪問另一塊數據: 列表本身的相關信息以及它們渲染哪個行哪個列 (如果在面向列的控制中)。這稱爲 listData
, 在 BookItemRenderer.mxml itemRenderer 示例中可以這樣使用它:
將這個代碼放入上述示例 BooktItemRenderer.mxml 代碼的 <mx:Script> 塊中。
itemRenderer 的 listData property
有一個 owner
字段, 它是 itemRenderer 所屬的控制。在本例中, 所有者是 MyTileList
控制-我的 TileList 擴展。將所有者字段轉換爲 MyTileList
即可取走標準。
IDropInListItemRenderer
當 itemRenderer 類實施 IDropInListItemRenderer 接口時, 即可訪問 listData
。不幸的是, UI 容器組件不實施提供 listData
訪問權的接口。Button 和 Label 等控制組件提供這一訪問權, 但對於容器, 您必須自己實施接口。
實施這個接口很簡單, 您可以在 Flex 文檔中找到說明。您必須爲 BookItemRenderer 類執行以下操作:
- 由類實施接口。
- 將
set
和get
函數添加到 itemRenderer 文件的 <mx:Script> 塊。
當列表控制看到 itemRenderer 實施 IDropInListItemRenderer 接口時, 它將創建一個 listData
項目並將它指派到每個 itemRenderer 實例。
invalidateList()
在我的類中設置這個標準並不像指派值這麼簡單。那樣做無法告知 Flex 框架數據已更改。標準更改必須觸發一個事件。以下是對 set criteria()
函數的修改內容:
注意, 一旦設置 _criteria
值, 它會調用 invalidateList()
。這將使用 dataProvider 的值重置所有 itemRenderer 並調用它們的 set data 函數。
隨後的流程如下:
- itemRenderer 在它的列表所有者中查找要使用的標準, 以幫助它決定如何渲染數據。
- 列表所有者類是某個 Flex 列表類的擴展, 它包含 itemRenderer 讀取以及外部代碼-另一個控制或 ActionScript 代碼 (可能是從遠程調用接收數據產生的) 設置的公共屬性。
- 設置列表屬性時, 它調用列表的 invalidateList() 方法。這觸發了 itemRenderer 刷新, 使它們重置自己的數據 (並返回第 1 步)。
活動
在之前的文章中, 我向您展示瞭如何藉助事件冒泡使 itemRenderer 與應用程序的其餘部分通信。我認爲這相當快。但我認爲還有更好的方法, 它符合 itemRenderer 負責展示數據、控制負責處理數據的想法。
MyTileList
控制的構思是, 它是可售書籍目錄的可見視圖。當用戶選中一本書籍並要購買它時, 列表控制應當將這個信息發送給應用程序。換言之:
<CatalogList bookBuy="addToCart(event)" />
萬事俱備, 事件冒泡並跳過 MyTileList
。冒泡方法沒有將事件 (bookBuy
) 與列表控制 (MyTileList
) 關聯在一起, 允許您將控制移到應用程序的其他部分。例如, 如果您在主 Application 中寫入 bookBuy
的事件偵聽器, 您無法將列表控制移到應用程序的其他部分。如果要移動, 您還得移動那個事件處理函數。另一方面, 如果您將事件與控制關聯在一起, 只是移動控制。
我們這樣看: 假設 Button 上的單擊事件並不是 Button 調度的事件, 但由於按鈕中的某個內容而冒泡。您將無法使用: <mx:Button click="doLogin()" label="Log in" />; 您必須將 doLogin()
函數放在其他位置, 這會使應用程序更難使用。
希望我已經說服您, 以下是如何將這個示例從冒泡更改爲從列表控制調度。
- 將元數據添加到 CatalogList 控制, 告知編譯器控制負責調度事件:
- 將一個函數添加到 CatalogList 進行事件調度。itemRenderer 實例將調用這個函數:
- 將 itemRenderer 中的 Buy 按鈕代碼更改爲調用該函數:
現在, itemRenderer 中的 Button 可以使用記錄數據 (或適合此操作的其他任何內容) 輕鬆調用列表控制中的函數, 並將與應用程序其餘部分協調的職責轉交給列表控制。
本例中的列表控制使用數據調度事件。應用程序可以使用 ActionScript 爲這個事件添加事件偵聽器, 也可以使用 MXML (因爲 CatalogList.as 文件中的 [Event]
元數據) ; 使用 [Event]
元數據使開發人員能更輕鬆地使用您的代碼。
後續工作
itemRenderer 應使用事件進行任何操作通信。自定事件允許您將信息隨事件傳遞, 這樣事件使用者無需再通過 itemRenderer 獲取數據。
itemRenderers 應通過覆蓋它們的 set data 函數對數據更改作出“反應”。在該函數中, 它們可以訪問其 listData.owner 中的值。它們還可以訪問存儲在靜態類或通過 Application.application 存儲在主應用程序中的數據。
在下一篇文章中, 我們將討論如何將狀態併入 itemRender 中。