天天看点

Flex数据绑定陷阱(二)

尝试绑定一个没有包含IPropertyChangeNotifier接口的类

实现IPropertyChangeNotifier接口的类,必须在类改变属性时派发事件并且任何嵌套类必须作为公共属性被曝光。

因此,你能发现类里的属性何时改变了。

例如,让我们来看一下UIComponent类的签名(见图3)。

UIComponent类确实实现了发布属性改变事件,这个一旦某个属性被改变就会派发一个事件的接口。

Flex数据绑定陷阱(二)

图3.UIComponent类的签名

现在看下下面这个控制用户信息的类:

  1. package vo
  2. {
  3.    public final class UserInfo
  4.    {
  5.       public var userName:String;
  6.       public var password:String;
  7.       public function UserInfo()
  8.       {
  9.       }
  10.    }
  11. }

复制代码

如果你尝试绑定用户信息类的 某个属性刀Label的text属性上,按照下面的说明这么写的话,这个绑定将不会成功:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"   
  3.    xmlns:s="library://ns.adobe.com/flex/spark"
  4.    xmlns:mx="library://ns.adobe.com/flex/mx"
  5.    minWidth="1024" minHeight="768"
  6.    creationComplete="creationCompleteHandler()">
  7.    <fx:Script>
  8.       <![CDATA[  
  9.          import vo.UserInfo;
  10.          [b][Bindable][/b]
  11.          private var userInfo:UserInfo = new UserInfo();           
  12.          protected function creationCompleteHandler():void
  13.          {
  14.             userInfo.userName = "EladElrom";
  15.          }
  16.       ]]>
  17.    </fx:Script>
  18.    <s:Label id="lbl" text="{userInfo.userName}" />
  19. </s:Application>

复制代码

因为这段代码尝试去绑定一个没有实现 IPropertyChangeNotifier接口的类,绑定机制将不会工作。

在这个例子中,你将看到问题窗口下的以下提示信息(见图4):

数据绑定将不能实现侦测userName的任务。

Flex数据绑定陷阱(二)

图4.问题面板显示的警告信息

要让前面的数据绑定能够工作,你可以将[Bindable]标签加到类声明前面。

这将使得这个类的所有公共属性能够被绑定。Flex的编译器将会为你生成公共的getter和setter方 法,这些将会包含使绑定工作的所有必要代码。

或者如果你不希望使类的所有属性都可以绑定,你可以将[Bindable]标签加到特定的属性前面。

  1. package vo
  2. {
  3.    [Bindable]
  4.    public final class UserInfo
  5.    {
  6.       public var userName:String;
  7.       public var password:String;
  8.       public function UserInfo()
  9.       {
  10.       }
  11.    }
  12. }

复制代码

ObjectProxy 类

数据绑定要求被绑定的类实现IPropertyChangeNotifier接口,否则该对象将不能被绑定。

尽管如此,类/属性或变量,如原始变量,没有标记[Bindable]标签不能实现这个接口。

如果这个类是你自己写的类,你所需要做的就是添加[Bindable]元数据标签。

如果不是你自己的类,你又希望绑定它,或你只是希望运行时添加绑定功能,你可以使用ObjectProxy类。

ObjectProxy封装一个没有绑定的类并在这个被绑定类的任何属性改变时派发属性改变事件,

使得你能监听你程序里的该对象的属性改变。

你可以在Adobe Flex 4语言参考里找到更多关于ObjectProxy类的更多信息。

下面的例子使用了ObjectProxy类。我创建了一个ObjectProxy的实例并把我希望看到的对象传给它,在这个例子里是 UserInfo。

接着我添加了一个事件监听,来跟踪UserInfo各项的改变。

  1. <?xml version="1.0" encoding="utf-8"?>         
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"            
  3.    xmlns:s="library://ns.adobe.com/flex/spark"
  4.    xmlns:mx="library://ns.adobe.com/flex/mx"
  5.    minWidth="1024" minHeight="768"                                    
  6.    creationComplete="creationCompleteHandler()">
  7.    <fx:Script>        
  8.       <![CDATA[
  9.          import mx.events.PropertyChangeEvent;
  10.          import mx.utils.ObjectProxy;
  11.          import vo.UserInfo;
  12.          private var userInfo:UserInfo = new UserInfo();
  13.          private var objectProxy:ObjectProxy;
  14.          protected function creationCompleteHandler():void
  15.          {
  16.             objectProxy = new ObjectProxy( userInfo );
  17.             objectProxy.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, onPropertyChange );
  18.             objectProxy.userName = "EladElrom";
  19.             objectProxy.password = "123";
  20.          }
  21.          private function onPropertyChange( event:PropertyChangeEvent ):void  
  22.          {   
  23.             lbl.text = event.newValue.toString();
  24.          }   
  25.       ]]>      
  26.    </fx:Script>  
  27.    <s:Label id="lbl" />
  28. </s:Application>

复制代码

一定要注意的一件事情是我们使用 ObjectProxy类是为了方便转让消息,注册的监听器会在每次改变目标对象时被调用。

这会在无形中引入一个重要开销,事实上在我们的例子中因为属性改变了两次所以onPropertyChange方法被调用了两次。

继续阅读