在ActionScript中创建自定义事件类来发送复杂数据
使用Flex可以创建一个使用自定义类型的事件对象的自定义事件。只需要创建一个扩展自Event类的子类然后向其中添加属性。不要忘了扩展自既有Flex类的自定义组件会继承基类的所有事件。
要创建一个自定义类我们需要创建一个扩展自flash.events.Event的ActionScript类,这个类将作为所有事件对象的基类。接下来,为了调用父类的构造方法并将事件类型传给它,我们要调用super()方法。我们还需要覆写 "clone()" 方法,通过设定type属性和其它一些属性来返回事件对象的一个拷贝。
为了从自定义组件中分派一个新的事件,我们创建了这个自定义类的一个实例并传送属性值给它。
现在我会用一个例子来说明这种方式。我们创建了一个简单的Blog阅读器,它允许用户使用下拉列表框从Blog列表中选择一个。这个程序由2个MXML组件组成,这两个组件是一个用来显示日志内容的DataGrid以及一个含有Blog列表下拉列表框。
我们将从一个自定义事件类(它被保存为"evtClass.as",并放在了”com”文件夹里)开始,它接受一个简单字符串属性:
package com
{
import flash.events.Event;
public class evtClass extends Event
{
public var evProp:String;
public function evtClass(evParam:String,type:String)
{
super(type);
this.evProp = evParam;
}
override public function clone():Event
{
return new evtClass(evProp,type);
}
}
}
象我们之前说的那样,这个类扩展自flash.events.Event类,调用了super()方法并且覆写了clone()方法。
现在,在Flex Builder 2中创建一个组件(File > New > MXML Component)并保存为custBlogList.mxml。这个组件包含有一个下拉列表框(ComboBox)并且它的dataProvider是一个ArrayCollection对象。
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Metadata>
[Event(name="changeBlog", type="com.evtClass")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import com.evtClass;
private function init():void
{
myArray.addItemAt({label:"Alistair McLeod", data:"http://weblogs.macromedia.com/amcleod/index.xml"}, 0);
}
private function changeHandler():void
{
var eventObj:evtClass = new evtClass(myCombo.value as String,"changeBlog");
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:ComboBox id="myCombo" change="changeHandler()" creationComplete="init();myCombo.selectedIndex=0" >
<mx:ArrayCollection id="myArray">
<mx:Object label="Mike Chambers" data="http://weblogs.macromedia.com/mesh/index.xml"/>
<mx:Object label="Matt Chotin" data="http://weblogs.macromedia.com/mchotin/index.xml"/>
</mx:ArrayCollection>
</mx:ComboBox>
</mx:VBox>
我们使用了[Event]元数据标签定义了这个MXML组件可以分派的事件。赋给type属性的值就是我们的自定义事件类:
[Event(name="changeBlog", type="com.evtClass")]
</mx:Metadata>
一旦用户在下拉列表框中选择了一个Blog,change事件就会被触发并且changeHandler()会被调用:
<mx:ComboBox id="myCombo" change="changeHandler()" creationComplete="init();myCombo.selectedIndex=0" >
这个事件处理器只有一个作用,就是创建一个自定义事件类的实例并将用户所选择的值传送给这个实例(将myCombo中的值作为一个字符串):
{
var eventObj:evtClass = new evtClass(myCombo.value as String,"changeBlog");
dispatchEvent(eventObj);
}
第二个MXML组件包含了DataGrid控件并且从主程序中接收dataProvider。现在你需要将这个文件保存为custBlogData.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import flash.net.*;
[Bindable]
public var lista:ArrayCollection;
]]>
</mx:Script>
<mx:DataGrid id="myDG" horizontalCenter="14" verticalCenter="18.5" dataProvider="{lista}" width="100%"
change="navigateToURL(new URLRequest(myDG.selectedItem.link),'_blank');" >
<mx:columns>
<mx:DataGridColumn headerText="Posts" dataField="title" />
<mx:DataGridColumn headerText="Date" dataField="pubDate" width="100" />
</mx:columns>
</mx:DataGrid>
</mx:VBox>
这个DataGrid定义了两列。第一列从用户选择的RSS feed(在custBlogList中选择的)中获取数据。第二列从类型为ArrayCollection 的变量"lista" 获取数据。
接下来,就是主程序文件了(BlogReader.mxml),它会调用上面的两个组件,调用一个HTTPService来获取rss数据并且定义了一个事件处理函数:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:cust="*"
creationComplete="hs.send()" >
<mx:HTTPService
id="hs"
url="{selectedMenu}"
useProxy="false"/>
<mx:Script>
<![CDATA[
import com.evtClass;
[Bindable]
private var selectedMenu:String= "http://weblogs.macromedia.com/amcleod/index.xml";
private function eventFired(event:evtClass):void
{
selectedMenu = event.evProp;
if (selectedMenu == "null")
{
mx.controls.Alert.show("Please Choose a valid Blog");
return;
};
hs.send();
}
]]>
</mx:Script>
<mx:Panel width="70%" height="70%" layout="absolute" title="Comtaste's Blog Reader" horizontalCenter="0"
verticalCenter="-14.5">
<mx:Label text="{hs.lastResult.rss.channel.title}'s Blog" id="myLbl" x="48.5" y="43" fontWeight="bold"/>
<cust:custBlogList x="161" y="10" changeBlog="eventFired(event)" />
<mx:Label x="48.5" y="10" text="Select a Blog" height="25"/>
<cust:custBlogData width="80%" x="48.5" y="69" lista="{hs.lastResult.rss.channel.item}" />
<mx:ControlBar>
<mx:Label text="Developed by Marco Casario" />
<mx:LinkButton label="http://casario.blogs.com" click="navigateToURL(new
URLRequest('http://casario.blogs.com'),'_blank');"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
HTTPService标签对它的url属性进行了数据绑定。当custBlogList中的changeBlog事件触发时{selectedMenu}的值就会被确定:
<mx:HTTPService
id="hs"
url="{selectedMenu}"
useProxy="false"/>
<cust:custBlogList x="161" y="10" changeBlog="eventFired(event)" />
eventFired()是一个事件处理器,它使用事件对象来获取在actionscript(evtClass.as)类中定义的evProp,它包含myCombo的值:
private function eventFired(event:evtClass):void
{
selectedMenu = event.evProp;
if (selectedMenu == "null")
{
mx.controls.Alert.show("Please Choose a valid Blog");
return;
};
hs.send();
}
松耦合的组件是Flex 2程序中一个强大的工具,因为这使得开发者可以提高代码的重用性和可维护性。使用这种方式可以定义在多个程序中都能使用的响应不同用户交互的逻辑模块。
模块也可以被自定义成包含有能够接收其它模块传值的属性以及可以返回信息的事件。