天天看点

[Flex 2] 06 Flex & XML

      在构建富因特网应用程序GUI方面有了很好处理能力后,现在我们把焦点转向向GUI中放入内容。如不能把它们与数据源联系起来,一切都无意义。

################

# 数据源

################

      过去,一般将数据库直接引用到动态页面模板。现在趋势是放弃过去做法,实现数据库与XML的混合。

    XML可使在因特网上交换数据变得轻松。因为它是基于文本的格式,故人与计算机均可毫无困难地阅读它。此外,它还足够灵活,可轻松适应各种情况。而大多数数据库都可以将数据输出成XML以供站点使用。

      这个新的模型相当流行,使得Macromedia公司去掉了Flex和Flash直接访问数据库的功能,取而代之的是允许程序轻松访问XML文件的大量类文件。

################

# 事件&事件对象

################

      每个类文件内部都有3个潜在的编程构造:属性(即位于类文件中的变量,而非函数中的变量)、函数和事件。

内置组件实际上都派生自AS类文件。故如在GUI中放一个Button控件,就会自动调用Button类文件及其相应属性、函数和事件。

      面向对象编程中一个总的编程原则:

            没有事件就什么也不会发生!

      应用程序的加载、数据加载的完成、按钮的单击和文本的键入等都可视为事件。没有事件的推动,就不会进一步发生什么。对所有OOP编程语言来说都是如此。

      在大多数编程环境里,Button组件中的click事件被称为事件监听器(event listener),即它唯一工作就是监听事件的发生。事件一旦发生,它就会告诉指定代码(事件处理器(event handler))去执行相应的任务。

编码工作,究其本质,即让我们能够对更加复杂的情况轻松地做出响应。

      在AS(以及今天大多数编程语言)中,当有事件发生时,就会生成一个名为事件对象(event object)的对象。此对象包含两段非常重要的信息:谁生成了事件,即目标(target);事件是什么,即类型(type)。当事件调用事件处理器时,它会传递一个参数(即事件对象)。

################

# XML

################

     业务逻辑即使用Java、ColdFusion、.NET或PHP之类的编程环境,为数据库的连接以及数据的插入、删除、读取和分发等确立所有规则。Flex(及Flash)目的是以友好的方式将数据呈现给用户。不过,业务逻辑层会确定在访问数据时哪些是允许的,哪些是不允许的。

    XML允许我们根据数据的特殊需要定义一套自己的标记。事实上,每个特定的行业都有专用的XML标记库,或称为词汇表(vocabulary)。

      例:

    <?xml version="1.0" encoding="iso-8859-1"?>

    <foed>

        <book ISBN="738493">

          <book_name>XML for Flash</book_name>

          <author>Sas Jacobs</author>

          <cover>assets/jacobs.jpg</cover>

        </book>

        <book ISBN="638212">

          <book_name>Foundation Flash 8 Video</book_name>

          <author>Tom Green</author>

          <cover>assets/green.jpg</cover>

        </book>

        <book ISBN="938201">

          <book_name>Object-Oriented Programming for Flash 8</book_name>

          <author>Peter Elst</author>

          <cover>assets/elst.jpg</cover>

        </book>

        <book>

          <book_name>Foundation ActionScript Animation: Making Things Move</book_name>

          <author>Keith Peters</author>

          <cover>assets/peters.jpg</cover>

        </book>

    </foed>

      可看出:首先,标记名称非常好地描述了它们所包含的数据;其次,起始标签对应结尾标签;第三,标签有严格的层级关系;第四,区分大小写。

      代码中有4个图书元素(element),即结点(node)。每个结点又有3个子元素:<book_name>、<author>和<cover>。除了这些子元素,每个结点还有一个名为ISBN的属性,这一切都包含在名为<foed>的根结点内。

      当Flex访问XML文件时,每个结点都会变成内存中的一个新的对象。

     (虽然我们将处理的是硬编码的XML文件,但在实际工作状态下,我们会提取XML文件中的结构,并将它与内存中的数据结合起来,因此每条记录会变成一个新的对象)

1 Model 标签

      处理XML文件可能性有3个:

      1)将XML数据直接嵌入在SWF文件中;(少见,且只能用于有限且不变的数据)

      2)有一个外部XML文件位于同一个服务器上;(常见)

      3)有一个外部XML文件位于完全不同的服务器上(更普遍)。

    Model类可以非常好地处理前两种情形。通过使用Model标签,Flex就不会在内嵌的XML文件和外部XML文件(source属性)之间区分。Model标签会在应用程序调用后立即自动运行。

2 HTTPService标签

    HTTPService可动态读取XML。即当特定事件发生时,SWF都会从XML文件请求最新数据。有时人们把这种行为称为异步请求(asynchronous request)。另外,通过HTTPService类,XML可以位于任意服务器,因为我们要指定XML文件的URL。

HTTPService类会使用send()方法调用数据。当SWF收到所有数据,就会产生一个名为result的事件。这会告诉事件监听方,数据可以用了。然后,HTTPService会把数据存储在一个名为lastResult的属性中以及ResultEvent类的result属性中。

例(后面会用):

      <--XML Contents-->

      <?xml version="1.0" encoding="iso-8859-1"?>

      <books>

        <stock>

          <name>The Picasso Code</name>

          <author>Dan Blue</author>

          <category>Fiction</category>

          <description>Cubist paintings reveal a secret society of people who really look like that</description>

        </stock>

        ...

        ...

      </books>

      <--Flex Code-->

      <mx:HTTPService id="bookData" url="assets/books.xml"/>

      调用数据:bookData.send()

        让XML文件发送其信息。实际过程中,它会将信息发送给Flash Player,然后就会设置好之前提到的对象。

      显示数据:<mx:DataGrid ... dataProvider="{bookData.lastResult.books.stock}"/>

      lastResult属性会在每次有刷新数据进入时进行自我更新。

3 Array & ArrayCollection

      对Array类,很多方法和属性都可以操作数组,但不能操作组成数组的基本数据,只有几个基本的函数例外。如,我们可以在数组的结尾或开头添加或删除数据。有不少方法是在数组内部进行操作。Array类没有任何事件,故做数据源不合适。

AS为我们提供了一种更加强大的类,名为ArrayCollection。它会把自己包裹在数组之外,从而使我们在很大程序上能够操作数据本身。与Array类相比,它增加了一些事件和方法,适合作数据源,即可以实现实时更新。

    HTTPService会自动把数组包裹在一个ArrayCollection对象中。

    AS有一个只处理Web服务和XML的类包,即rpc(remote procedure component,远程过程组件)包。rpc包有一个名为ResultEvent的类,其主要功能是生成一个对象,并在XML数据成功汇集到之前讨论的对象中的时候加以报告。

    [Bindable]标签会告诉AS在源更新时更新目的文件。

    <--Code-->

    <mx:Script>

    <![CDATA[

      import mx.rpc.events.*;

      import mx.collections.*;

      import mx.rpc.events.*;

      [Bindable]

      private var bookStock:ArrayCollection;

      private function bookHandler(evt:ResultEvent):void{

          bookStock = evt.result.books.stock;

      }

    ]]>

    </mx:Script>

    <mx:HTTPService id="bookData" url="assets/books.xml" result="bookHandler(event)"/>

    <mx:DataGrid ... dataProvider="{bookStock}"/>

      报告与远程组件(XML文件或远程组件)连接的错误,需要FaultEvent类、HTTPService类的fault事件及一个事件处理器(函数)。

4 E4X入门简介

    ///据作者言,以本书时间为准,则E4X当时还未成熟,有不确定性

     目前为止,AS还没有办法直接处理XML数据,只能把它转换成ArrayCollection,即前所述。

     新兴标准为E4X(或称ECMAScript for XML)。

     使用需改HTTPService的属性resultFormat="e4x",则可使用XML数据如下:

      <--Script-->

      private var bookStock:XMLList; //XML类处理的主要是XML对象的创建和删除;

                              //XMLList类处理的则是这些对象的操作;

                       //即,如打开的是已存在的XML文件(如此处),用XMLList;如在应用程序内创建XML对象,用XML类

          private function bookHandler(evt:ResultEvent):void{

          trace(evt.result.stock.name);

          trace(evt.result..author);//后代访问符(descendant accessor)

          trace(evt.result.stock.(category=='Fiction'));//搜索stock结点

      }

################

# DataGrid

################

1 修改 DataGrid 列

<--Code-->

<mx:DataGrid dataProvider="">

<mx:columns>

<mx:DataGridColumn dataField="name" headerText="Book Name"/>

<mx:DataGridColumn dataField="author" headerText="Book Author"/>

...

</mx:columns>

</mx:DataGrid>

dataField 指定要显示的是哪一个结点;

headerText 指定列名;

2 更改日期格式

    <mx:DateFormatter>标签允许我们通过使用formatString属性为日期预定义格式,如"MMMM DD, YYYY";

      不能直接将格式应用到DataGrid控件的字段,只能通过函数:

      <--Script-->

      private function dateFormat(dateItem:Object, publish_date:DataGridColumn):String{

        return publishDate.format(dateItem.publish_date);

        //其中,publishDate为DateFormatter对象(即前面所说的<mx:DateFormatter>标签)

        //第1个参数dataItem类型必须是Object,表示一行数据

        //第2个参数类型必须是DataGridColumn,是想要进行格式化的列的名称

        //返回类型为String

      }

      然后须将DataGrid控件绑定到这个函数上,即DataGridColumn的属性labelFunction="dateFormat";

3 编辑和显示数据

      修改DataGrid或DataGridColumn属性editable="true"使其相应对象可编辑。

      修改DataGridColumn属性itemEditor="mx.controls.TextArea"或itemRenderer="mx.controls.TextArea"(风格不同)将TextArea放入字段。

      如需在一个单元格中包含多个控件,则需要自定义组件,再添加DataGridColumn值。

4 应用

      很多显示对象的控件,如DataGrid、ComboBox和List,都允许我们单击列表中的项。被选中的项叫做selectedItem。从一个selectedItem到下一个selectedItem的移动会构成更改事件(change event)。它会生成一个类型为Event的事件对象。我们由此可以创建事件处理器。

<--End-->