`

Flex数据绑定

阅读更多
1、 数据绑定失败

  public var _barDataArray:ArrayCollection;
[Bindable]
private var datas:ArrayCollection = new ArrayCollection();

public function set barDataArray(array:ArrayCollection):void {
_barDataArray = array;
dispatchEvent(new Event("barDataChanged"));

}

[Bindable(Event="barDataChanged")]
public function get barDataArray():ArrayCollection {
  datas.removeAll();
  for each (var bar:BarData in _barDataArray) {
datas.addItem({barName:bar.barName,barValue:bar.barValue});
}
return _barDataArray;
}

使用的地方:
<app:AmBarChartsView id="storageBars" barDataArray="{storageBarsData}" width="50%" height="100%"/>

结果:绑定无效, 断点调试发现, 能够进入set barDataArray(array:ArrayCollection)中但是不会进入get barDataArray()方法中。

  后经同事协助,发现是因为barDataArray并未在别处被绑定 

  于是在调用的页面作出修改如下:
<fx:Binding source="storageBars.barDataArray" destination="storageBarsData2" />
        private var storageBarsData2:ArrayCollection;
运行,发现绑定成功.其关键是barDataArray要被绑定... ...
但让人纳闷的是数据绑定失败并不会抛出异常


2、  拓展之flex数据绑定
2.1、绑定机理
   Flex实际上在编译的时候会产生一些Watcher代码去监视绑定标签所指定的表达式。在运行的时候,当绑定源的属性得到修改,那么这个Watcher监视类就会触发change事件去执行绑定更新的工作。

2.2 flex数据绑定的三种方式
    A、{}
在{}绑定方式中,可以绑定property,ActionScript expressions,E4
X expression和ActionScript functions。绑定一个属性或者一段AS的表达式已经应用的非常普遍了。偶尔我们需要用到绑定的是一个AS的函数,但是,绑定一个函数的时候很多人会碰到问题,为什么我的数据没有自动更新呢?本人也曾经碰到过,看了开发文档才知道,原来忽略了一个细节问题。

就是在绑定函数的时候,通常情况下需要一个bindable的property作为该函数的参数。

<?xml version="1.0"?>
<!-- binding/ASInBraces.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
      <![CDATA[
      [Bindable]
      public var inString:String;
      public function getNewText(sourceString:String):String {
             return sourceString.toUpperCase();
       }
       ]]>
</mx:Script>
       <mx:TextInput id="myTI" text="Enter text here"/>
       <mx:Button label="Trigger Binding" click="inString=myTI.text;"/>
       <mx:TextArea text="{getNewText(inString)}"/>
</mx:Application>
这里的inString一旦发生改变,会直接触发函数getNewText进行重新执行。
但如果你将函数的参数inString去掉,而直接放到getNewText()中,那么这个函数会在系统初始化的时候执行一次,而起不到绑定的效果。我可是在实际开发中有深刻体会。


   B、<mx:Binding> tag in MXML
用<mx:Binding>标签效果和{}一样,只需要指定source和destination两个属性即可,如果要设置双向绑定,则添加属性twoWay=true即可。
   C、BindingUtils methods in ActionScript

2.3 数据绑定除了会延缓程序的初始化之外还有如下一些陷阱(转载)
   A、 难以发现的无声错误
   B、 调试绑定
    使用BindingManager.as和Binding.as来进行调试并不容易,因为如果你没有下载完整的Flex sdk的话,绑定类是没有的。相反,你可以设置一个断点并跟踪相关的绑定对象来找出问题所在。另一种方法更加直观,是使用BindingManager类的debugBinding方法。你设置你想观察的组件和属性,然后你就可以看到被捕获的错误:
   BindingManager.debugBinding("label.text");

  以下有一些在绑定时可能抛出的错误类型:

    * Error #1006: Call attempted on an object that is not a function.
    * Error #1009: Null has no properties.       
    * Error #1010: Undefined has no properties.       
    * Error #1055: Has no properties.
    * Error #1069: Property - not found on - and there is no default value
       
    *错误#1006:试图调用的对象不是函数。
    *错误#1009:空没有属性。
    *错误#1010:未定义没有属性。
    *错误#1055:没有属性。
    *错误#1069:属性 - 找不到 - 并且没有默认值

      
3、 flex中使用ofc2抛出异常:
     TypeError: Error #1009: 无法访问空对象引用的属性或方法。
at JsonInspector$/has_pie_chart()[/home/t/project/etaum/report/client-app/flex/ofc/src_k/JsonInspector.as:16]
at Chart/build_chart()[/home/t/project/etaum/report/client-app/flex/ofc/src_k/Chart.as:438]
at Chart/parse_json()[/home/t/project/etaum/report/client-app/flex/ofc/src_k/Chart.as:393]
at Chart/addedToStage()[/home/t/project/etaum/report/client-app/flex/ofc/src_k/Chart.as:100]
at flash.display::DisplayObjectContainer/addChildAt()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::$addChildAt()[E:\dev\4.0.0... ...
   错因在于<ofc:Chart charData={chartJson}... .../>中的chartJson为null所致。
   解决方案:可以写成charData=" ",加载时先判断chartJson对应的变量是否为空,当部位空时再将其赋给charData。在as块中声明chartJson变量时如下:
   private var chartJson:String;即可,而不要使用
   private var chartJson:String="";

4、 关于flex组件显示不完全的问题?
   找到该组件的父页面,在父页面中进行控制

5、 关于使用FlexEvent.CREAT_COMPLETE事件来实现单例模式
    ...
    this.addEventListener(FlexEvent.CREAT_COMPLETE,init());
    ...
    private function init(){... ... }


6、 关于flex dataGrid中设置显示行数无效的一种情况
    当对dataGrid同时设置了height与rowCount后,rowCount中指定的行数无效,其会按照height指定的高度来显示。

7、 关于你的代码写得很烂的探讨... ...


8、 什么是敏捷之道?
   问题的关键是如何有效地获取用户需求... ...

——————Flex数据绑定专题——————————————————————
当属性成为数据绑定表达式源时,Flex 在源属性发生变化时自动将源属性的值拷贝给目的
属性。为了告知Flex 去执行这个拷贝工作,必须用[Bindable]元数据标记将这个属性注册到
Flex 中,并且源属性必须发出一个事件。
[Bindable] 元数据标记语法如下:
[Bindable]
[Bindable(event="eventname")]
如果忽略事件名称,Flex 会自动创建一个名为propertyChange,类型为
PropertyChangeEvent 的事件。
可以在三个地方使用[Bindable]元数据标记:

1. 在public 类定义之前使用

2、在public,protected 或者private 属性之前使用该标记可以将这个特定的属性定
义为支持数据绑定

3、3. 在由getter 或者setter 方法所定义的public,protected 或者private 属性之前使用该标记。
  这种情况下,要想使用[Bindable]标记必须为属性同时定义setter 和
getter 方法。如果只是定义了一个setter 方法,那么你就创建了一个“只写”属性,
这样的属性不能作为数据绑定表达式的源。如果只定义getter 方法,那么就创建了
一个“只读”属性,把只读属性当作数据绑定源而不插入[Bindable]标记,就如同
使用了一个用const 关键字定义的变量来作为数据绑定表达式的源。(这样的绑定
源只能在应用启动时触发绑定一次,以后就不会再触发)。

这个标记可以由下面的形式定义:
[Bindable]
public function set shortNames(val:Boolean):void {
...
}
public function get shortNames():Boolean {
...
}
Flex 编译器自动为这个属性产生一个名为propertyChange,类型为
PropertyChangeEvent 的事件。如果属性值在写入的时候保持不变,Flex 不会发出
事件或者更新属性。为了确定属性是否变化,Flex 调用getter 方法来获取属性的当
前值。
也可以为事件指定名称,如下例所示:
[Bindable(event="changeShortNames")]
public function set shortNames(val:Boolean):void {
...
// Create and dispatch event.
dispatchEvent(new Event("changeShortNames"));
}
// Get method.
public function get shortNames():Boolean {
...
}
这种情况下,开发者要负责生成和发出事件。通常是在setter 方法中完成这个工作。
并且Flex 不会检查旧值和新值是否不同。尽管在类的级别上指定了[Bindable]标记,如果
想要为事件命名,仍然可以在[Bindable]中包含指定名称的事件。
下面的代码使以变量形式定义的maxFontSize 和minFontSize 属性可以作为数据绑定的
源:
// Define public vars for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
在下面的例子中,使setter 和getter 方法形式定义的public 属性成为数据绑定的源。
[Bindable]元数据标记中引入了属性变化时由setter 方法发出的事件:
// Define private variable.
private var _maxFontSize:Number = 15;
[Bindable(event="maxFontSizeChanged")]
// Define public getter method.
public function get maxFontSize():Number {
return _maxFontSize;
}
// Define public setter method.
public function set maxFontSize(value:Number):void {
if (value <= 30) {
_maxFontSize = value;
} else _maxFontSize = 30;
// Create event object.
var eventObj:Event = new Event("maxFontSizeChanged");
dispatchEvent(eventObj);
}
在这个例子中,setter 更新了属性的值,然后创建并发出了一个事件来激发对数据绑定目的
属性的更新。




在MXML 文件中,通过在<mx:Metadata>块中引入[Bindable]元数据标记,就可以将所有以变量
形式定义的public 属性成为数据绑定的源,例子如下:
<mx:Metadata>
[Bindable]
</mx:Metadata>


使用可绑定属性链进行工作

当指定一个属性作为数据绑定表达式的源时,Flex 不仅监控这个属性的变化,也会监控这
个由这个属性作为开始点的属性链的变化。整个属性链,包括源属性,被称为“可绑定的属性
链”。在下面的例子中,firstName.text 是一个可绑定的属性链:
<mx:Text id="myText" text="{firstName.text}"/>
开发者可以使用很长的属性链,如下例所示:
<mx:Text id="myText" text="{user.name.firstName.text}"/>
只有当text 属性是可绑定的,数据绑定机制才能检查text 属性的变化。但是,如果在运
行时,想要向属性链中的部分属性赋予新值,那么属性链中的每个属性都必须是可绑定的,才
能使数据绑定机制起作用。否则,在运行时更改user,name 或者firstName 属性会导致数据绑
定机制无法检查text 属性的变化。

在使用BindingUtils.bindProperty()或者BindingUtils.bindSetter()方法时,可以将可
绑定的属性链作为方法的参数,例如,bindProperty()方法有以下的声明:
public static function bindProperty(site:Object, prop:String, host:Object,
chain:Object, commitOnly:Boolean = false):ChangeWatcher
Host 和chain 属性指定了数据绑定表达式的源。使用bindProperty()方法可以定义一个
数据绑定表达式,如下:
bindProperty(myText, 'text', user, ["name","firstName","text"]);
这个例子中,["name","firstName","text"]定义了相对于user 对象的可绑定属性链。注
意,在本例中,user 不是可绑定属性链的一部分。
在MXML 数据绑定表达式中,可绑定属性连总是相对于this。因此,要想定义一个同上面的
MXML 等价的数据绑定表达式,应按如下例子使用bindProperty()方法:
bindProperty(myText, 'text', this, ["user", "name","firstName","text"]);



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics