针对只读属性使用[Bindable]

建立一個 NameVO 如下所示:
 
Actionscript:
  1. Class NameVO {
  2.   private var _firstName: String = "";
  3.   private var _lastName: String = "";
  4.     // read only //
  5.   [Bindable ]
  6.   public function get fullName ( ): String {
  7.     return _firstName + _lastName;
  8.   }
  9.   //write only //
  10.   public function set firstName ( value: String ): void {
  11.     _firstName = value;
  12.   }
  13.   //write only //
  14.   public function set lastName ( value: String ): void {
  15.    _lastName = value;
  16.   }
  17. }

然後呢,我希望我的label可以直接binding 此fullName屬性,也就是說,當_lastName或_firstName改變時,fullName也會跟著改變!像這樣子:

 
XML:
  1. <mx:Label text="{vo.fullName}" />

 

好,一切準備就緒,完整的運用:

 
XML:
  1. <script>
  2.  [Bindable]public var vo:NameVO = new NameVO("Robert", "Shiue");
  3. </script>
  4. <mx:Label text="{vo.fullName}"/>
  5. <mx:Button click="vo.lastName='Hseuh'"/>

 

理想的情況應該是:
Label文字由"RobertShiue" 變成 "RobertHseuh"才是,然而,事與願違。
為什麼呢? 該怎麼作? 請繼續閱讀...

這樣才是有用的:

 
Actionscript:
  1. private var _lastName: String = "";
  2. private var _firstName: String = "";
  3.  
  4. public function set lastName ( value: String ): void {
  5.    _lastName = value;
  6.    dispatchEvent ( new Event ( "propertyChange" ) );
  7. }
  8.  
  9. public function set firstName ( value: String ): void {
  10.    _firstName=  value;
  11.    dispatchEvent ( new Event ( "propertyChange" ) );
  12. }
  13.  
  14. [Bindable ]
  15. public function get fullName ( ): String {
  16.     return _firstName + _lastName;
  17. }

 

[Bindable]的剖析:
請看這篇文章,找到Ely Greenfield的回覆,有一段這麼說道:

Instead when you put [Bindable] on a get/set property, the compiler makes it bindable with a little creative rewriting that allows the framework to watch the get function, and dispatch a change event when the get function is triggered. This means that automatic bindable properties don’t work when the get function is computed from multiple values, or when you change its value by setting a backing field, rather than using the set function.
...
if you have no set function, we can pretty much guarantee that there’s no way automatically bindable get properties will be triggered.a read only properties, to the compiler, completely opaque…at the moment, it has no idea where that value is coming from, and hence will never be able to ‘automatically’ trigger the binding.

簡單地解釋:如果一個getter吐出的結果是眾多變數的計算結果;而非單一變數的值,那麼[Bindable]在該getter上不會發生作用。因為getter裡的數值可能來自不同的變數,Compiler無法亦不想去檢視裡頭的各種變數是否改變了,假設getter裡所運算的變數都是Bindable,可是Binding 所發出的事件名不同(i.e [Bindable(event="anotherEvent")] ),該怎麼辦,因此,AS compiler不會這麼作。Ely Greenfield也說明了如果真要Compiler去檢驗裡頭所有的變數,那程式將會非常地沒有效率,這並非[Bindable]tag 的本意。[Bindable]是Flex Framework自動幫該變數實作event-listening的標示,自動地幫你實作該變數的getter/setter 函式,且在變數改變時,發出event(預設是"propertyChange")。

當然,也可以發出自己設定的事件:

 
Actionscript:
  1. public function set myName ( value: String ): void {
  2.   _name = value;
  3.   dispatchEvent ( new Event ( "nameChange" ) );
  4. }
  5.  
  6. [Bindable (event= "nameChange" ) ]
  7. public function get myFullName ( ): String {
  8.   return _name + _lastname;
  9. }

 

如果真的要作出上述的效果,那必須自己在setter裡頭發出event,然後監聽之。
然後,還要特別注意的,就是[Bindable]唯有該變數被set才會改變,只是該變數的某個屬性改變,並不能啟動Binding的機制,舉例來說:

 
Actionscript:
  1. [Bindable ] public var list:Foo = new Foo ( "test" );
  2.  
  3. list = new Foo ( "testing" ); //Binding 有效!
  4. list. someBoo = "some values"; //Binding 無效!

[Bindable]幫你實作出來的程式,是在setter裡發出propertyChange事件,不管該變數所包含的其他屬性的。
使用[Bindable]請小心。

更多參考:
官方文件: metadata tag
使用Binding

你可能感兴趣的:(xml,Flex,idea,actionscript)