——告诉编译器如何编译
转载: http://flexhome.javaeye.com/blog/152024
虽然多数Flex开发者都使用过[Bindable]标签,但是很多人都不知道这个标签的作用甚至不知道该标签为何物。[Bindable]就是所谓的元数据标签。元数据标签是一种特殊的标签,它在代码中的作用就是向编译器提供如何编译程序的信息。实际上,这些标签并没有被编译到生成的SWF文件中,而只是告诉编译器如何生成SWF文件。文档中列出的元数据标签共有12个,本文将讲解这些元数据标签的定义并给出使用它们的示例,在看完这篇文章之后,你就会明白应该在何时何处在你的Flex 2应用程序中使用元数据标签了。
[ArrayElementType]
实际上,定义一个数组通常来说是一件很平常的事情,因为数组中的元素可以是任何类型的。不过,使用ArrayElementType元数据标签可以让你定义数组元素的数据类型。下面的例子展示了如何使用[ArrayElementType]:
程序代码
[ArrayElementType("String")]
public var arrayOfStrings:Array;
[ArrayElementType("Number")]
public var arrayOfNumbers:Array;
[ArrayElementType("mx.core.UIComponent")]
public var arrayOfUIComponents:Array;
[Bindable]
Bindable元数据标签是最经常用到的一个元数据标签,因为它使程序组件之间的数据同步变得很容易。Bindable可以用来绑定简单数据类型、类、复杂数据类型以及函数。绑定数据的时候,你必须先使用元数据标签定义一下数据,
Bindable也可以用来绑定到事件。Listing 2展示了如何使用getter和setter函数将一个属性绑定到一个事件上。这个例子中有一个叫做phoneNumber的私有变量,还有一个公有的setter和getter函数。使用Bindable标签将这个getter方法绑定到了一个叫做phoneNumberChanged的事件上,只要数据发生改变setter方法就会分派phoneNumberChanged事件。通过使用setter方法,可以在数据赋予私有变量之前对其进行操作。在这个例子中,数据只有在长度大于等于10的时候才会被格式化。当phoneNumberChanged事件被分派的时候,第二个TextInput组件会被更新,因为他的text属性绑定到了phoneNumber变量上。
当一个属性来自一个数据表达式,当源属性改变时,Flex自动复制源属性的值到任何目标属性。为了标示着一复制,你必须使用[Bindable]元数据标签在flex中注册这一属性,并且源属性必须发送一个事件。
[Bindable]元数据标签采用以下格式
[Bindable]
[Bindable(event="eventname")]
如果你省略了事件名,flex自动创建一个事件名propertyChange
你可以在三个地方使用[Bindable]元数据标签
1、在public class定义前
[Bindable]元数据标签绑定所有的作为变量定义的public属性,并且所有的public属性都定义有getter和setter方法。在这种情况下,[Bindable]没有参数,例如:
[Bindable]
public class TextAreaFontControl extends TextArea {}
flex编译器自动创建一个事件名叫propertyChange用于所有的公有属性,这些属性可以作为绑定表达式的源。这种定义等同于
[Bindable(event="propertyChange")]
如果属性值的改变与原来相同,flex并不传递这个事件或更新属性。
2、在public, protected 或 private 属性前,格式为:
[Bindable]
public var foo;
3、Before a public, protected, or private property defined by a getter or setter method.
你必须同时定义getter和setter方法,以便于使用[Bindable]元数据标签。
[Bindable]
public function set shortNames(val:Boolean):void {
...
}
public function get shortNames():Boolean {
...
}
你可以使用自定义的事件名,如:
[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 {
...
}
// Define public vars for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
// 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);
}
[DefaultProperty]
DefaultProperty元数据标签用来将一个单一属性设定为某个类的默认属性。它允许在一个容器标签内设定属性,而不用定义属性的名字。一个简单的例子就是一个自定义Button类。Listing 3展示了一个简单的Button类,它将label属性设定为了DefaultProperty。
Listing 1 A simple use of [Bindable]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF">
<mx:Script>
<![CDATA[
[Bindable]
private var me:String="Rich Tretola";
]]>
</mx:Script>
<mx:Panel title="Simple Binding" width="500" height="90"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom=" 10" layout="horizontal">
<mx:Label text="{me}"/>
</mx:Panel>
</mx:Application>
Listing 2 Using [Bindable] with getters and setters
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private var _phoneNumber:String = �";
// Bind getter function to phoneNumberChanged event
[Bindable(event="phoneNumberChanged")]
public function get phoneNumber():String {
return _phoneNumber;
}
// Setter method.
public function set phoneNumber(value:String):void {
if (value.length<10) {
_phoneNumber = value;
} else {
_phoneNumber = phoneFormatter.format(value);
}
// Create and dispatch event
var eventObj:Event = new Event(損honeNumberChanged");
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:PhoneFormatter id="phoneFormatter"
formatString="(###) ###-####" validPatternChars="#-()
�/>
<mx:Panel title="Bind with Getters and Setters"
width="500" height="90"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom=" 10" layout="horizontal">
<mx:TextInput id="ti1" change="phoneNumber=ti1.text"
maxChars="10" restrict="0-9"/>
<mx:TextInput id="ti2" text="{phoneNumber}"/>
</mx:Panel>
</mx:Application>
Listing 3 Custom Button class named MyButton
package
{
import mx.controls.Button;
[DefaultProperty(搇abel")]
public class MyButton extends Button
{
}
}
Listing 4 Using the MyButton class wih [DefaultProperty]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:comps="*">
<comps:MyButton>
<mx:String>Test</mx:String>
</comps:MyButton>
</mx:Application>
Listing 5 Custom ButtonLabel class using [Event]
package
{
import mx.controls.Button;
import flash.events.Event;
// Define the custom event
[Event(name="labelChanged", type="flash.events.Event")]
public class ButtonLabel extends Button {
// property to hold label value
private var _myLabel:String;
// public setter method
public function set myLabel(s:String):void {
_myLabel = s;
this.label = s;
// Create and dispatch custom event
var eventObj:Event = new Event(搇abelChanged");
dispatchEvent(eventObj);
}
}
}
Listing 6 Using the ButtonLabel class with the labelChanged [Event]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:comps="*"
backgroundColor="#FFFFFF">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import flash.events.Event;
// method to handle custom event
public function labelChanged(eventObj:Event):void {
myTA.text= myTA.text + 揬n"+ eventObj.target.label;
myTA.verticalScrollPosition = myTA.verticalScrollPosition +
20;
}
]]>
</mx:Script>
<mx:Panel title="Event Sample" width="500" height="275"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom=" 10" layout="absolute">
<mx:TextInput id="buttonLabelTI"
change="myButton.myLabel=buttonLabelTI.text" x="10" y="9"/>
<!--Instantiate custom class and define method to handle label-
Changed event-->
<comps:ButtonLabel id="myButton" labelChanged="labelChanged(event)
;"
x="10" y="39"/>
<mx:TextArea id="myTA" width="200" height="200" x="249" y="10"/>
</mx:Panel>
</mx:Application>
Listing 7 Add the Effect metadata tag
...
// Define the custom event
[Event(name="labelChanged", type="flash.events.Event")]
[Effect(name="labelChangedEffect", event="labelChanged")]
public class ButtonLabel extends Button {
...
Listing 8 Add labelChangedEffect to the Component
Instantiation MXML Tag
<comps:ButtonLabel id="myButton" labelChanged="labelChanged(event);"
labelChangedEffect="myEffect" x="10" y="39"/>
Listing 9 Custom component with [Inspectable] defined
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Inspectable(defaultValue="Visa",
enumeration="Visa,Mastercard,Discover,American Express"
category="Credit Card" type="String")]
public var ccType:String;
]]>
</mx:Script>
</mx:HBox>
Listing 10 Using [NonCommittingChangeEvent]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF">
<mx:Script>
<![CDATA[
import flash.events.Event;
private var eventObj:Event;
[Bindable(event="triggerBinding")]
[NonCommittingChangeEvent(揷hange")]
private var s:String;
private function triggerBinding():void{
eventObj = new Event(搕riggerBinding");
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:Panel title="NonCommittingChangeEvent Sample" width="500"
height="90"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom=" 10" layout="horizontal">
<mx:TextInput id="ti1" change="s=ti1.text" enter="triggerBinding()"
/>
<mx:TextInput id="ti2" text="{s}" />
</mx:Panel>
</mx:Application>
Listing 11 Custom Class CustomCircle using [Style] tags
package
{
import mx.core.UIComponent;
[Style(name="borderColor",type="uint",format="Color",inherit="no")]
[Style(name="fillColor",type="uint",format="Color",inherit="no")]
public class CustomCircle extends UIComponent {
public function CustomCircle(){
super();
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
graphics.lineStyle(1, getStyle(揵orderColor"), 1.0);
graphics.beginFill(getStyle(揻illColor"),1.0);
graphics.drawEllipse(0,0,100,100);
}
}
}
Listing 12 Using CustomCircle and assigning custom style properties
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:comps="*"
backgroundColor="#FFFFFF">
<mx:Panel title="Style Sample" width="200" height="200"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom=" 10" layout="horizontal">
<comps:CustomCircle borderColor="#000000" fillColor="#FF0000" />
</mx:Panel>
</mx:Application>