Flex 中的元数据标签
2008-10-12 18:11 宝宝合凤凰 阅读(2021) 评论(0) 编辑 收藏 举报Flex 中的元数据标签
2008-3-10 12:24:26
Flex 元数据标签——告诉编译器如何编译
虽然多数Flex开发者都使用过[Bindable]标签,但是很多人都不知道这个标签的作用甚至不知道该标签为何物。
[Bindable]就是所谓的元数据标签。元数据标签是一种 特殊的标签,它在代码中的作用就是向编译器提供如何编译程序的信息。实际上,这些标签并没有被编译到生成的SWF文件中,而只是告诉编译器如何生成SWF 文件。文档中列出的元数据标签共有12个,本文将讲解这些元数据标签的定义并给出使用它们的示例,在看完这篇文章之后,你就会明白应该在何时何处在你的 Flex 应用程序中使用元数据标签了。
[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可以用来绑定简单数据类型、类、复杂数据类型以及函数。绑定数据的时候,你必须先使用元数据标签定义一下数据,正如Listing 1中所示的那样。图1是Listing 1的代码运行结果。
图1:
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>
Bindable也可以用来绑定到事件。Listing 2展 示了如何使用getter和setter函数将一个属性绑定到一个事件上。这个例子中有一个叫做phoneNumber的私有变量,还有一个公有的 setter和getter函数。使用Bindable标签将这个getter方法绑定到了一个叫做phoneNumberChanged的事件上,只要 数据发生改变setter方法就会分派phoneNumberChanged事件。通过使用setter方法,可以在数据赋予私有变量之前对其进行操作。 在这个例子中,数据只有在长度大于等于10的时候才会被格式化。当phoneNumberChanged事件被分派的时候,第二个TextInput组件 会被更新,因为他的text属性绑定到了phoneNumber变量上。
图2和图3显示了Listing 2代码的运行结果。
图2:
图3:
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("phoneNumberChanged");
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>
[DefaultProperty]
DefaultProperty元数据标签用来将一个单一属性设定为某个类的默认属性。它允许在一个容器标签内设定属性,而不用定义属性的名字。一个简单的例子就是一个自定义Button类。Listing 3展示了一个简单的Button类,它将label属性设定为了DefaultProperty。Listing 4展示了label属性是如何在自定义Button标签中作为一个字符串定义的。
Listing 3 Custom Button class named MyButton
package
{
import mx.controls.Button;
[DefaultProperty(“label")]
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>
[Embed]
Embed元数据标签用来导入图片到程序。可以通过两种方式使用Embed。你可以将图片嵌入到ActionScript中并将其指派给一个变量(如同下面代码中的第一个例子),或者你也可以将图片直接指派给组件的属性(使用下面代码中的第二个例子所示的语法规则)。
例1:
[Embed(source=”myIcon.gif”)]
[Bindable]
public var myIcon:Class;<mx:Button label=”Icon Button 1″ icon=”{myIcon}”/>
<mx:Button label=”Icon Button 2″ icon=”{myIcon}”/>
例2:
<mx:Button label=”Icon Button 1″ icon=”@Embed(source='myIcon.gif’)”/>
<mx:Button label=”Icon Button 2″ icon=”@Embed(source='myIcon.gif’)”/>
上面这两个例子产生的结果是一样的。创建myIcon类的好处是,它在一个类中只定义一次并可以绑定到程序中的多个组件。
[Event]
Event元数据标签用来声明那些被自定义类分派的事件。将这个元数据标签添加到类定义中之后,你就可以在MXML标签中添加事件处理函数来初始化该自定义类。Listing 5创建了一个自定义Button类,每当它的label属性改变的时候就会分派一个事件。Listing 6所显示的主程序文件初始化了这个自定义Button并创建了事件处理函数,该函数将新的labe属性值赋给了一个TextArea组件以显示当前发生的更改。
图4显示了Listing 5 和 Listing 6中的代码运行结果。
图4:
Listing 5 Custom ButtonLabel class using
[Event(name="load_complete",type="com.eastcomsw.rpc.event.RemoteDataLoaderEvent")]
new RemoteDataLoaderEvent(RemoteDataLoaderEvent.LOAD_COMPLETE,e,typeID);
跟在RemoteDataLoaderEvent类里定义一个静态变量一个效果
[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(“labelChanged");
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>
[Effect]
Effect元数据标签用来定义一个自定义效果,当某个事件发生的时候该效果会被分派。这个示例可以基于前面Event的例子来创建,通过简单地更改ButtonLabel类(Listing 7)中的一行代码,就定义了一个效果,该效果可以在MXML标签中直接使用(Listing 8)。
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"/>
<mx:Blur id="myEffect" blurXFrom="100" blurYFrom="100" blurXTo="0" blurYTo="0"/>
[IconFile]
IconFile 是用来定义一个jpg,gif或者png文件的文件名的,它在你的自定义类中作为图标来使用。[Embed]元数据标签可以用来嵌入图片、SWF文件、音 乐文件以及视频文件等,而IconFile则只是用来嵌入用来作为自定义类图标的文件。下面是一个IconFile的例子:
[IconFile(”icon.png”)]
public class CustomButton extends Button{}
[Inspectable]
在使用Flex Builder 2的时候,你可能会希望某些自定义组件的属性在代码提示和属性检查器(property inspector)中显示,Inspectable元数据标签就是用来定义那些属性的。Listing 9展示的例子定义了一个inspectable的ccType变量,它定义了Visa为默认值、Credit Card为类别并将取值范围定义为包含了Visa, Mastercard, Discover, 和 American Express的枚举。
图5展示了当将组件添加到程序中的时候所显示的代码提示。
图5:
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>
图6与上面展示的是同样的代码,但是这次是设计视图,所以我们能看到属性检查器。你可以看到属性ccType的类别为Credit Card,它的所有可选的值都在下拉列表中。
图6:
[InstanceType]
当在一个模板对象中声明一个像IDeferredInstance这样的变量时,InstanceType元数据标签就用来声明对象的类型。下面是InstanceType的用法:
[InstanceType(”package.className”)]
[NonCommittingChangeEvent]
NonCommittingChangeEvent元数据标签在某个特定事件发生的时候可以防止变量在事件发生的过程中被更改。Listing 10展 示了它是如何工作的。一个名为s的字符串类型的私有变量被绑定到了名为ti2的TextInput组件上。另外一个id为ti1的TextInput组件 在它的text发生更改的时候就会将s的值设置为它的text属性的值。另外,当triggerBinding 事件被分派的时候,附加在s变量上的Binding元数据标签就会进行绑定。只有在Enter键在ti1 TextInput组件中被按下时才会分派triggerBinding事件。
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(“change")]
private var s:String;
private function triggerBinding():void{
eventObj = new Event(“triggerBinding");
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>
[RemoteClass]
RemoteClass 可以用来将一个ActionScript类绑定到一个Java类或一个ColdFusion CFC。这样做可以自动转换数据类型。下面的例子将包com.mydomain中的名为MyClass的ActionScript类绑定到了同一个包中名为MyClass的Java类:
package com.mydomain {
[Bindable]
[RemoteClass(alias=”com.mydomain.MyClass”)]
public class MyClass {
public var id:int; public var myText:String;
}
}
[Style]
Style元数据标签用来为组件定义自定义样式属性的。只需要简单地将Sytle元数据标签添加到类的定义当然,然后就可以使用getSytle方法获取它的值了。Listing 11 和 12中的例子定义了两个样式,分别为borderColor 和fillColor,它们的数据类型都是uint。当类初始化的时候这两个样式就会在标签中被设定。代码中覆写了updateDisplayList函数,用自定义的样式画了一个圆形边框并将其填充。
图7展示了Listing 11 和 Listing 12中代码运行的结果。
图7:
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(“borderColor"), 1.0);
graphics.beginFill(getStyle(“fillColor"),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>
现在你应该会有这样的感觉了:“喔,现在我知道在哪里可以使用它们了”或者“嗯,我想我会在新的项目中尝试使用这些元数据标签”。如果你没有,那么你可能需要回过头去再看一遍这篇文章。OK,我想说的是Adobe Flex小组提供给我们的元数据标签不只是非常的强大,可以让我们扩展或自定义我们要做的东西,而且它还非常易于使用。通过使用它们,仅仅几行代码就可以完成一大堆事情。如果不使用这些标签,你会发现在Flex 2中实现一些东西是很辛苦的。
文件上沒記載的
[SWF] [SWF(width="300", height="200", frameRate="18", backgroundColor="#FFFFFF")]
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:comps="*" frameRate="31" width="400">
<mx:Metadata>[SWF(width="200", height="200", frameRate="31", backgroundColor="#FFFFFF")]
</mx:Metadata>
<mx:Script>
---------------------------------------- [RemoteClass] [RemoteClass(alias="flex.messaging.io.ArrayCollection")] [RemoteClass(alias="flex.messaging.io.ArrayList")] [Frame] [Frame(factoryClass="mx.managers.SystemManager")] [Frame(factoryClass="mx.core.FlexApplicationBootstrap")] [Frame(extraClass="Obj")] [ExcludeClass] [DefaultBindingProperty] [DefaultBindingProperty(destination="dataProvider")] [DefaultTriggerEvent] [DefaultTriggerEvent("itemClick")] [DefaultTriggerEvent("scroll")] [Exclude] [Exclude(name="defaultButton", kind="property")] [Exclude(name="horizontalScrollPolicy", kind="property")] [Exclude(name="icon", kind="property")] [Exclude(name="label", kind="property")] [Exclude(name="tileHeight", kind="property")] [ResourceBundle] [ResourceBundle("validators")] [ResourceBundle("SharedResources")] [ResourceBundle("foo")] [PercentProxy] [PercentProxy("percentHeight")] [RequiresDataBinding] [RequiresDataBinding(true)] [CollapseWhiteSpace] [MaxChildren] [MaxChildren(0)] [AccessibilityClass] [AccessibilityClass(implementation="mx.accessibility.PanelAccImpl")] [AccessibilityClass(implementation="mx.accessibility.TitleWindowAccImpl")]
<![CDATA[
===========================================================
http://flex.sys-con.com/node/361239
Most Flex developers have seen and used the [Bindable] tag but not many know what this tag does or even what it is. [Bindable] is what is known as a metadata tag. Metadata tags are special tags that are inserted in your source code that give the compiler information on how to compile the application. These tags aren't actually compiled into the generated SWF file but provide instructions on how the compiler should create the SWF. There are 12 documented metadata tags. This article will offer definitions of these metadata tags and give examples of their use. By the end of this article you will understand when and where to use metadata tags in your Flex 2 applications.
[ArrayElementType]
Defining an array is usually very generic in nature because the elements of the array can be any type. However, using the ArrayElementType metadata tag lets you define the data types of the array elements. Here is the sample syntax of [ArrayElementType]:
[ArrayElementType("String")]
public var arrayOfStrings:Array;
[ArrayElementType("Number")]
public var arrayOfNumbers:Array;
[ArrayElementType("mx.core.UIComponent")]
public var arrayOfUIComponents:Array;
[Bindable]
The Bindable metadata tag is one of the most used metadata tags because it allows for easy data synchronization within the components of your application. Bindable can be used to bind simple data, classes, complex data, and functions. To bind a simple piece of data, you must simply define the data with the metadata tag included, as shown in Listing 1. Figure 1 shows the results of Listing 1
Bindable also allows binding to events. Listing 2 shows how to bind a property using getters and setters, along with an event binding. This example has a private variable named phoneNumber, as well as a public getter and setter. The getter method uses the Bindable tag to bind to an event named phoneNumberChanged. This setter method dispatches the phoneNumberChanged even whenever its data changes. By using a setter method, the data can be manipulated before it's set to the private variable. In this example, the data is formatted only when the length of the value coming into the method is 10. When the phoneNumberChanged event is dispatched, the second TextInput component updates because its text property is bound to the phoneNumber variable.
Figure 2 and Figure 3 show the results of Listing 2.
[DefaultProperty]
The DefaultProperty metadata tag is used to set a single property as a default property of a class. This allows the property to be set within a container tag without needing to define the property name. A simple example of this would be a custom Button class. Listing 3 shows a simple Button class that has the label property set as the DefaultProperty. Listing 4 shows how the label is defined as a string within the custom Button container tags.
[Embed]
The Embed metadata tag is used to import images into your application. There are two ways to use Embed. You can either embed the image in ActionScript and assign it to a variable (as in the first example in the following code), or you can assign it directly to the component property (using the syntax shown in the second example of the following code).
[Embed(source="myIcon.gif")]
[Bindable]
public var myIcon:Class;
<mx:Button label="Icon Button 1" icon="{myIcon}"/>
<mx:Button label="Icon Button 2" icon="{myIcon}"/>
The output from the following is identical to the previous code block. The benefits of creating the myIcon class are that it can be defined one time in a single class and bound to multiple components in your application.
<mx:Button label="Icon Button 1" icon="@Embed(source=myIcon.gif')"/>
<mx:Button label="Icon Button 2" icon="@Embed(source=myIcon.gif')"/>
[Event]
The Event metadata tag is used to declare events that will be dispatched by your custom class. Adding this metadata tag to your class definition allows you to add an event handler function to the MXML tag used to instantiate your custom class. Listing 5 creates a custom Button class that will dispatch an event whenever its label property changes. The main application file shown in Listing 6 instantiates the custom Button and creates the event handler function, which dumps the new label property to a TextArea component to show the occurring changes.
Figure 4 shows the results of Listing 5 and Listing 6.
[Effect]
The Effect metadata tag is used to define a custom effect that will be dispatched when an event occurs. This can be easily demonstrated by building on the earlier Event examples. By simply changing a single line to the ButtonLabel class (Listing 7), an effect is defined that can be assigned to an Effect instance (Listing 8).
[IconFile]
IconFile is used to identify the filename of a jpg, gif, or png file that will be used as the icon for your custom class. While the [Embed] meta tag can be used to embed images files, SWF files, music files, video files, etc, IconFile is only used to embed a file that will be used as the icon for the custom class. Here is the example of the IconFile syntax:
[IconFile("icon.png")]
public class CustomButton extends Button
{
}
[Inspectable]
The Inspectable metadata tag is used to define the attributes of your custom component that you would like to display in the code hints and property inspector of Flex Builder 2. The example shown in Listing 9 defines a variable named ccType that is inspectable. It defines a defaultValue of Visa, a category of Credit Card and enumeration values of Visa, Mastercard, Discover, and American Express.
Figure 5 shows the example of the code hints being displayed as the component is added to an application.
Figure 6 shows the same example, but this time in design view, which exposes the property inspector. You can see that the category of properties is Credit Card with the property showing as ccType and the available values in the drop-down.
[InstanceType]
The InstanceType metadata tag is used to declare the type of object that will be allowed when declaring a variable as IDeferredInstance in a template object. The syntax of InstanceType looks like this:
[InstanceType("package.className")]
[NonCommittingChangeEvent]
The NonCommittingChangeEvent is a metadata tag that will prevent a change from occurring when a specified event occurs. Listing 10 demonstrates how this works. A private variable named s of type String is created and bound to the ti2 TextInput component. The other TextInput component with the id of ti1 sets the value of s equal to the value of its text property whenever the text changes. Additionally, the Binding metadata tag attached to the s variable is set to bind when the triggerBinding event is dispatched. The triggerBinding event is dispatched only when the Enter key is pressed while typing in the ti1 TextInput component.
[RemoteClass]
RemoteClass can be used to bind an ActionScript class to a Java class or a ColdFusion CFC. This will allow for automatic data type conversions. Below is a sample of an ActionScript class named MyClass in the package com.mydomain being bound to a Java class named MyClass in the package com.mydomain:
package com.mydomain {
[Bindable]
[RemoteClass(alias="com.mydomain.MyClass")]
public class MyClass {
public var id:int;
public var myText:String;
}
}
[Style]
The Style metadata tag is used to define custom style properties for your components. Simply add the Style metadata tag or tags to your class definition and then use the getStyle method to retrieve its value.
Listings 11 and 12 give examples of how to define two styles named borderColor and fillColor, both of which are defined as a uint data type. The styles are set in the component tag when the class is instantiated. The updateDisplayList function is overridden and the custom styles are used to draw the circle border and fill.
Figure 7 shows the results of Listing 12 and Listing 13.
By now you should have had a few "Wow, I know where I could have used that" or "Hmm, I think I will try this metadata tag in a new project." If you haven't, then you need to go back and read the article again. OK, so what I'm trying to say is that the metadata tags provided for us by the Adobe Flex team are not only extremely powerful, allowing us to extend and customize what we do with Flex, but are also very easy to use. They are a very quick way to accomplish a great deal with only a few lines of code. If you're not using these tags, you're working too hard to accomplish things that are built into Flex 2.
The content of this article is excerpted from the upcoming book titled Professional Flex 2 (ISBN 0470102675) by Rich Tretola, Simon Barber, and Renaun Erickson from Wiley Publishing, Inc./Wrox Press. To pre-order please visit http://www.everythingflex.com/ or www.amazon.com/Professional-Flex-2-Rich-Tretola/dp/0470102675.
====================================================================================