﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-【永恒的瞬间】  -文章分类-flex2Cairngorm</title><link>http://www.blogjava.net/19851985lili/category/19815.html</link><description>☜GivE mE HapPy ☞




</description><language>zh-cn</language><lastBuildDate>Sat, 03 Mar 2007 03:19:57 GMT</lastBuildDate><pubDate>Sat, 03 Mar 2007 03:19:57 GMT</pubDate><ttl>60</ttl><item><title>Flex中自定义事件</title><link>http://www.blogjava.net/19851985lili/articles/101171.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 28 Feb 2007 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/101171.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/101171.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/101171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/101171.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/101171.html</trackback:ping><description><![CDATA[
		<div class="tit">Flex中的事件机制</div>
		<div class="date">2006-11-28 10:37</div>
		<table style="TABLE-LAYOUT: fixed">
				<tbody>
						<tr>
								<td>
										<div class="cnt">一. 事件简介 <br />事件可以由外设触发, 比如:键盘,鼠标, 也可能是外部输入, 比如:web service的返回. <br />事件还能由组件的外观和生命周期发生变化时触发, 比如:组件的创建或者改变大小. <br />所有用户与应用交互都会产生事件.用户没有直接与应用交互也可能产生事件, 比如:数据装载完毕. <br />你可以在程序中使用事件监听器监听这些事件. 事件监听器是函数方法用于响应指定的事件. 有时也称之为事件处理器. <br />Flex的事件模型基于DOM3事件模型. <br />组件产生派发事件并消费(监听)其他事件.如果一个对象想要了解其他对象事件的信息, 可以注册一个监听器. <br />当事件发生时,对象派发此事件到所有注册过的监听器中. <br />组件有Flex提供的内建事件. 也可以使用派发-监听模型定义自己的事件监听器, 并指定监听器监听何种事件. <br />二. 事件流简介 <br />当一个事件被派发出来时, 事件对象从根节点开始自上而下开始扫描display list, 一直到目标对象, 检查每个节点是否有相应的监听器. <br />目标对象指的是display list中产生事件的对象. 比如: <br />&lt;mx:Panel&gt; <br />&lt;mx:HBox&gt; <br />&lt;mx:VBox&gt; <br />&lt;mx:Button /&gt; <br />&lt;/mx:VBox&gt; <br />&lt;/mx:HBox&gt; <br />&lt;/mx:Panel&gt; <br />如何此时 resize了VBox, 则会从根(Application)开始, 下来检查Panel, HBox, 直到目标对象-产生resize事件的VBox为止. <br /><br />三. 事件的派发 <br />Flex中可以通过dispatchEvent()方法手工派发事件, 所有UIComponent的子类都可以调用此方法. <br />语法: <br />objectInstance.dispatchEvent(new Event("event_type"):Boolean <br />参数event_type是Event对象的type属性. 函数的返回值总是True. <br />可以使用此方法派发任意事件, 而不仅仅是用户自定义事件, 比如: 可以派发一个Button的Click事件. <br />var result:Boolean = buttonInstance.dispatchEvent(new Event(MouseEvent.CLICK)); <br /><br />在Flex应用中不是必须对新派发的事件进行处理, 如果触发了一个事件, 而没有对应的Listener时,Flex忽略此事件. <br />如果想给Event对象添加新属性, 就必须继承Event类,然后定义新属性 <br /><br />四.事件的传播: <br />事件触发后, Flex有3个检测事件监听器的阶段, 3个阶段的发生的顺序如下: <br />1. 捕获 <br />2. 目标 <br />3. 上浮 <br />在任意一个阶段, 节点们都有机会操作事件. 比如: 用户点击了一个在VBox中的Button, <br />在捕获阶段, Flex检查Application对象(根节点)和VBox是否有监听器处理此事件. Flex然后在目标阶段触发按钮的监听器. <br />在上浮阶段, VBox和应用以与捕获阶段相反的顺序再次获得机会处理事件. <br />在Action<font size="+0">script</font>3.0中,你可以在任意目标节点上注册事件监听器. 但是部分事件会被直接传给目标节点,比如Socket类. <br />捕获阶段的节点顺序是从父节点到子节点的, 而上浮阶段刚好相反. <br />捕获事件缺省是关闭的,也就是说如果要捕获事件, 必须显式指定在捕获阶段进行处理. <br />每一个Event都有target和currentTarget属性, 帮助跟踪事件传播的过程. <br /><br />捕获阶段: <br />在捕获阶段,Flex在显示列表中检查事件的祖先是否注册了事件的监听器. Flex从根节点开始顺序而下. <br />大多数情况中, 根节点是Application对象. 同时, Flex改变事件的currentTarget值. <br />缺省情况下, 在此阶段,没有容器监听事件. use_capture参数的值是False,在此阶段添加监听的唯一方法是在调用add_listener时, <br />传入一个为True值的use_capture参数, 比如: <br />myAccordion.addEventListener(MouseEvent.MOUSE_DOWN, customLogEvent, true); <br />如果是在Mxml中添加监听, Flex设置此参数为False, 没有办法进行修改. <br />如果设置了use_capture为True, 那么事件将不会上浮. 如果既想捕获又想上浮就必须调用 addEventListener两次. <br />一次use_capture参数为true, 一次为false; <br />捕获很少使用, 上浮的使用更为普遍. <br /><br />目标阶段: <br />在目标阶段, Flex激发事件的监听程序, 不检查其他的节点. <br /><br />上浮阶段: <br />事件只在bubbles属性为True时才进行上浮. 可以上浮的事件包括: change, click, doubleClick, keyDown, keyUp, mouseDown, mouseUp. <br />在上浮阶段, Flex改变事件的currentTarget属性, 而target属性是初始派发事件的对象. <br /><br />查询事件阶段: <br />使用事件的eventPhase可以获得事件当前的阶段, <br />1: CAPTURE_PHASE <br />2: AT_TARGET <br />3: BUBBLING_PHASE <br />示例: private function determineState(event:MouseEvent):Void { Debug.trace(event.eventPhase + ":" + event.currentTarget.id); } <br /><br />停止传播: <br />使用下面两个函数停止事件的传播: <br />stopPropagation() <br />stopImmediatePropagation()<br /><br /></div>
								</td>
						</tr>
				</tbody>
		</table>件是一个非常有用的功能，通常用于信息传递交互大大提高程序编写的灵活性。在高级语言中都会集成这方面特性；Flex也不例外几乎所有控件中都集成了大量的事件，如果Button的Click事件等。但实际应用中控件自有的事件是不能满真实需要的，特别在自己编写自定义控件时，自定义控件内部信息的改变如何及时通知所在的容器变得很更要；这个时候自定义事件就起到它的作用。<br /><br />       在Flex中定义事件有两中情况，分别是ActionScript和MXML中定义。<br /><br />       在ActionScript中定义：<br /><br /><div class="smalltxt" style="FONT-WEIGHT: bold; MARGIN-LEFT: 2em; MARGIN-RIGHT: 2em"><div style="FLOAT: left">CODE:</div><div style="FLOAT: right; TEXT-ALIGN: right"><a class="smalltxt" href="http://www.flashbbs.org/thread-163-1-1.html###"><font color="#800080">[Copy to clipboard]</font></a></div></div><div class="altbg2" style="CLEAR: both; BORDER-RIGHT: #698cc3 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #698cc3 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 3px 2em 2em; BORDER-LEFT: #698cc3 1px solid; WORD-BREAK: break-all; PADDING-TOP: 5px; BORDER-BOTTOM: #698cc3">[Event(name="myEnableEvent", type="flash.events.Event")]<br /><br />public class MyComponent extends UIComponent<br /><br />{<br /><br />           ...<br /><br />}</div>在MXML中定义：<br /><br /><div class="smalltxt" style="FONT-WEIGHT: bold; MARGIN-LEFT: 2em; MARGIN-RIGHT: 2em"><div style="FLOAT: left">CODE:</div><div style="FLOAT: right; TEXT-ALIGN: right"><a class="smalltxt" href="http://www.flashbbs.org/thread-163-1-1.html###"><font color="#800080">[Copy to clipboard]</font></a></div></div><div class="altbg2" style="CLEAR: both; BORDER-RIGHT: #698cc3 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #698cc3 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 3px 2em 2em; BORDER-LEFT: #698cc3 1px solid; WORD-BREAK: break-all; PADDING-TOP: 5px; BORDER-BOTTOM: #698cc3">&lt;mx:Metadata&gt;<br /><br />    [Event(name="DataChange", type="DataChangeEvent")]<br /><br />&lt;/mx:Metadata&gt;</div>DataChangeEvent事件参数的定义：<br /><br /><div class="smalltxt" style="FONT-WEIGHT: bold; MARGIN-LEFT: 2em; MARGIN-RIGHT: 2em"><div style="FLOAT: left">CODE:</div><div style="FLOAT: right; TEXT-ALIGN: right"><a class="smalltxt" href="http://www.flashbbs.org/thread-163-1-1.html###"><font color="#800080">[Copy to clipboard]</font></a></div></div><div class="altbg2" style="CLEAR: both; BORDER-RIGHT: #698cc3 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #698cc3 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 3px 2em 2em; BORDER-LEFT: #698cc3 1px solid; WORD-BREAK: break-all; PADDING-TOP: 5px; BORDER-BOTTOM: #698cc3">import flash.events.Event;<br /><br />public class DataChangeEvent extends flash.events.Event<br /><br />{<br /><br />       public function DataChangeEvent()<br /><br />       {<br /><br />              super("DataChange");<br /><br />       }<br /><br />       public var Data:Object;<br /><br />}<br /><br /></div>在自定义控件中定义和触发事件:<br /><br /><div class="smalltxt" style="FONT-WEIGHT: bold; MARGIN-LEFT: 2em; MARGIN-RIGHT: 2em"><div style="FLOAT: left">CODE:</div><div style="FLOAT: right; TEXT-ALIGN: right"><a class="smalltxt" href="http://www.flashbbs.org/thread-163-1-1.html###"><font color="#800080">[Copy to clipboard]</font></a></div></div><div class="altbg2" style="CLEAR: both; BORDER-RIGHT: #698cc3 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #698cc3 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 3px 2em 2em; BORDER-LEFT: #698cc3 1px solid; WORD-BREAK: break-all; PADDING-TOP: 5px; BORDER-BOTTOM: #698cc3">&lt;?xml version="1.0" encoding="utf-8"?&gt;<br /><br />&lt;mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="212" height="56"&gt;<br /><br />&lt;mx:Metadata&gt;<br /><br />        [Event(name="DataChange", type="DataChangeEvent")]<br /><br />    &lt;/mx:Metadata&gt;<br /><br />&lt;mx:Button label="Button" click="Change()"/&gt;<br /><br />       &lt;mx:Script&gt;<br /><br />              &lt;![CDATA[<br /><br />                     function Change():void<br /><br />                     {<br /><br />                            this.dispatchEvent(new DataChangeEvent());<br /><br />                     }<br /><br />              ]]&gt;<br /><br />       &lt;/mx:Script&gt;<br /><br />&lt;/mx:Form&gt;</div>容器接收相关自定义控件事件：<br /><br /><div class="smalltxt" style="FONT-WEIGHT: bold; MARGIN-LEFT: 2em; MARGIN-RIGHT: 2em"><div style="FLOAT: left">CODE:</div><div style="FLOAT: right; TEXT-ALIGN: right"><a class="smalltxt" href="http://www.flashbbs.org/thread-163-1-1.html###"><font color="#800080">[Copy to clipboard]</font></a></div></div><div class="altbg2" style="CLEAR: both; BORDER-RIGHT: #698cc3 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #698cc3 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 3px 2em 2em; BORDER-LEFT: #698cc3 1px solid; WORD-BREAK: break-all; PADDING-TOP: 5px; BORDER-BOTTOM: #698cc3">&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="*"&gt;<br /><br />      <br /><br />       &lt;ns1:EmployeeCombo x="146" y="132" DataChange="onChange(event)" &gt;<br /><br />       &lt;/ns1:EmployeeCombo&gt;<br /><br />       &lt;mx:Script&gt;<br /><br />              &lt;![CDATA[<br /><br />                     import mx.controls.Alert;<br /><br />                     function onChange(e:DataChangeEvent)<br /><br />                     {<br /><br />                           <br /><br />                     }<br /><br />              ]]&gt;<br /><br />       &lt;/mx:Script&gt;<br /><br />&lt;/mx:Application&gt;</div>其实自定义事件的现实也很简单,但起着非常重要的作用；正是因为有了事件的机制，使得大部分重复的功能抽取到自定义控件中，从而达到一个很高的代码重用性。<img src ="http://www.blogjava.net/19851985lili/aggbug/101171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-28 17:00 <a href="http://www.blogjava.net/19851985lili/articles/101171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>架构一个Flex应用程序</title><link>http://www.blogjava.net/19851985lili/articles/101169.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 28 Feb 2007 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/101169.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/101169.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/101169.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/101169.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/101169.html</trackback:ping><description><![CDATA[
		<div align="center">架构一个<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Flex</b>应用程序</div>
		<br />
		<br />使用<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Flex</b>的web开发者可能最初会对用户界面模型感到困惑。虽然传统的、类似servlet的、请求-响应（request-response）模型将会在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Flex</b>中应用，但是却存在一种更好的方法。由于ActionScript语言中的“[Binding]”标签，你可以把你的视图绑定到模型数据，这样一来模型的更改就会自动影响到视图。<a href="http://www.adobe.com/devnet/flex/articles/cairngorm_pt1.html" target="_blank" tip="">Cairngorm</a> 微型架构使这种方法得到形式化，而且它也是那些想要领会如何“让它们在一起工作”的开发者的一个非常好的起点。在这篇文章中我将描述变量绑定，特性驱动开发和Carigorm在<a href="http://labs.adobe.com/wiki/index.php/NoteTag" target="_blank" tip="">NoteTag</a>中是如何一起工作的<br /><br />这里是一个典型的<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Flex</b>应用程序可能的架构：<br /><img alt="" src="http://www.zhuoqun.net/attachments/month_0607/x2006717223142.JPG" border="0" /><br /><br />域（Domain）<br />·组成域模型的所有类。在NoteTag中，它包含了Notes（记录），Tasks（事务）以及Subscriptions（订阅）（Subscriptions是相关Notes或Tasks的一个群集（collection））。<br /><br />模型（Model）<br />·一个保存域模型的可绑定实例的一个单体（singleton）。在NoteTag中，ModeLocator单体保存了用户的订阅清单，用户的连接，当前的订阅，当前的记录以及其他。<br /><br />视图（View）<br />·UI组件（通常来说就是MXML文件，虽然并不总是）。依赖状态（state-dependent）的UI组件被绑定到ModeLocator的实例变量。如果ModeLocator中数据被标记为“[Bindable]”，那么它的任何改变都会导致UI自动更新。NoteTag中的一个例子就是NoteListView，它显示了当前订阅中的记录列表。如果当前的订阅或者它的任何一个记录改变了，那么NoteListView将会自动更新来反应这些改变。<br /><br />控制器（Controller）<br />·同事件驱动的Commands一样执行特性所需的下部构造。NoteTag中的例子包括GetSubscriptionCommand, GetNoteCommand 以及其他。<br /><br />业务（Business）<br />·完成域中对象操作的业务逻辑类，经常呼叫远程服务并且异步返回结果。对大部分NoteTag的业务逻辑来说SubscriptionManager类是entry point。<br /><br />服务（Service）<br />·服务层，保存了用来呼叫远程服务（HTTPService,RemoteService和WebService）的所有类。NoteTag 使用了一个服务工厂（factory）类集合，减轻了对特殊的HTTP服务的部署，这些HTTP服务来自进行HTTP 服务呼叫的组件。<br /><br />多数应用程序特性都有上面的一些或者全部结构。下面是一个典型特性的工作流程：<br />1.视图（view）广播一个事件。<br />2.单体控制器（controller）收到这个事件，把它映射到相应的Command，并且执行这个Command。<br />3.Command委托适当的业务（Business）对象执行业务逻辑。<br />4.业务（Business）对象执行业务逻辑，可能对不同的Service进行一个或者多个异步呼叫，并且通过分派（dispatch）一个新的事件给Command来返回结果。<br />5.Command将结果赋给单体模型。<br />6.绑定到单体模型中的数据的所有视图都自动更新。<br /><br />它是如何在一个特定的特性中工作的呢？当用户从Notes列表（看下面，在屏幕的顶端）中选中了一个Note时，这个Note就会从适当的存储（Blogger或TypePad）中加载并显示在编辑器中（看下面，在屏幕的底端）：<br /><a href="http://blogs.adobe.com/kiwi/2006/05/images/03_notetag_published_note.jpg" target="_blank" tip=""><img alt="" src="http://www.zhuoqun.net/attachments/month_0607/l2006717223820.JPG" border="0" /></a><br /><br /><strong>1.广播事件</strong><br /><br />当用户在第一个Note上点击时，NoteListView分派一个事件，如下：<br /><div class="UBBPanel"><div class="UBBTitle"><img style="MARGIN: 0px 2px -3px 0px" alt="程序代码" src="http://www.zhuoqun.net/images/code.gif" /> 程序代码</div><div class="UBBContent">// NoteListView.mxml<br />private function getSelectedEntry(event:<a name="baidusnap1"></a><b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">ListEvent</b>) : void<br />{<br />  var selectedEntry:TagBasedEntry =<br />    TagBasedEntry(currentFeed.entries[event.rowIndex-1]);<br />  Application.application.dispatchEvent(<br />    new GetNoteEvent(selectedEntry.metadata,true));<br />}</div></div><br /><br /><strong>2. 对事件相应</strong><br /><br />因为NoteTag的Front Controller已经把它自身注册来监听所有的Command Event，当GetNoteEvent 被分派的时候它将会被通知。<br /><div class="UBBPanel"><div class="UBBTitle"><img style="MARGIN: 0px 2px -3px 0px" alt="程序代码" src="http://www.zhuoqun.net/images/code.gif" /> 程序代码</div><div class="UBBContent">// NoteTagController.as<br />public class NoteTagController extends FrontController<br />{<br />  public function NoteTagController()<br />  {<br />    addCommand(LoginEvent.EVENT_LOGIN, LoginCommand);<br />    addCommand(GetNoteEvent.EVENT_GET_NOTE, GetNoteCommand);<br />    addCommand(GetTaskEvent.EVENT_GET_TASK, GetTaskCommand);<br />    addCommand(PostNoteEvent.EVENT_POST_NOTE, PostNoteCommand);<br />    // more commands...<br />  }<br />}</div></div><br /><br />Cairngorm的 Front Controller通过执行适当的command提供了监听事件和响应事件的基础构造。<br /><br /><strong>3. 执行 Command</strong><br /><br />为了获得这个Note，NoteTag需要呼叫存储了用户note的blog服务器。实现了Cairngorm的Command接口的GetNoteCommand就像这样：<br /><br /><div class="UBBPanel"><div class="UBBTitle"><img style="MARGIN: 0px 2px -3px 0px" alt="程序代码" src="http://www.zhuoqun.net/images/code.gif" /> 程序代码</div><div class="UBBContent">// GetNoteCommand.as<br />internal class GetNoteCommand extends ChainedCommand<br />{<br />  public override function execute(event:CairngormEvent):void<br />  {<br />    var initialEvent:GetNoteEvent = GetNoteEvent(event);<br /><br />    var subscriptionManager:SubscriptionManager =<br />      ModelLocator.getInstance().subscriptionManager;<br /><br />    setNextEventHandler(subscriptionManager,<br />      handleLoadNote,<br />      LoadNoteEvent.EVENT_LOAD_NOTE,<br />      onSubscriptionFault,<br />      SubscriptionFaultEvent.EVENT_SUBSCRIPTION_FAULT);<br />    subscriptionManager.loadNote(initialEvent.metadata);<br />  }<br /><br />  private function handleLoadNote(event:LoadNoteEvent):void<br />  {<br />    // handle result here...<br />  }<br /><br />  // ...<br />}</div></div><br /><br />（你可能已经发现了GetNoteCommand 继承了 ChainedCommand——这个类使用setNextEventHandler 方法共同进行一系列异步呼叫。在以后的文章里，我将更深入地讨论ChainedCommand，并大体说一下异步回应器（responder）。）<br /><br /><strong>4. 执行业务逻辑</strong><br /><br />SubscriptionManager通过执行对tag服务器和blog服务器一系列的HTTP service呼叫来触发Note的加载。当note被加载完毕时，SubscriptionManager 将分派一个LoadNoteEvent，这个事件将会被GetNoteCommand.handleLoadNote（参见下一条）触发。<br /><br /><strong>5. 更新模型</strong><br /><br />GetNoteCommand 通过把加载的Note赋给ModelLocator中适当的数据成员来响应事件。<br /><div class="UBBPanel"><div class="UBBTitle"><img style="MARGIN: 0px 2px -3px 0px" alt="程序代码" src="http://www.zhuoqun.net/images/code.gif" /> 程序代码</div><div class="UBBContent">// GetNoteCommand.as<br />internal class GetNoteCommand extends ChainedCommand<br />{<br />  // ...<br /><br />  private function handleLoadNote(event:LoadNoteEvent):void<br />  {<br />    ModelLocator.getInstance().currentNote = event.note;<br />  }<br /><br />  // ...<br />}</div></div><br /><br /><strong>6. 更新视图</strong><br /><br />任何绑定到ModelLocator的currentNote成员的视图都将会自动更新来反映新的数据。NoteView，负责在编辑器中显示Note的组件，是这样的一个视图：<br /><div class="UBBPanel"><div class="UBBTitle"><img style="MARGIN: 0px 2px -3px 0px" alt="程序代码" src="http://www.zhuoqun.net/images/code.gif" /> 程序代码</div><div class="UBBContent">// NoteView.mxml<br />&lt;mx:VBox xmlns:mx="<a href="http://www.adobe.com/2006/mxml" target="_blank" tip="">http://www.adobe.com/2006/mxml</a>"<br />    xmlns:view="com.adobe.kiwi.notetag.view.*"<br />    xmlns="*"&gt;<br />  &lt;mx:Script&gt;<br />  &lt;![CDATA[<br />    import com.adobe.kiwi.notetag.model.*;<br />    [Bindable] private var model:ModelLocator = ModelLocator.getInstance();<br />  ]]&gt;<br />  &lt;/mx:Script&gt;<br /><br />  &lt;view:NoteEdit id="noteEditor" width="100%" height="100%"<br />    note="{model.currentNote}" /&gt;<br /><br />&lt;/mx:VBox&gt;</div></div><br /><br />所有的其它特性——发布一个Note，获得一个Subscription，更新一个Task——会通过同样的Event-to-Command-to-Model-to-View途径来实现。Command-specific事件可以从多种内容中被分派，，而不需要知道哪一个视图会被影响。视图可以绑定到模型的变化而并不需要知道引发的事件是从什么地方被分派的。由于松耦合，出现了更清洁，更容易维护的代码。<br /><img src ="http://www.blogjava.net/19851985lili/aggbug/101169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-28 16:55 <a href="http://www.blogjava.net/19851985lili/articles/101169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 DataGrid 中分页显示记录</title><link>http://www.blogjava.net/19851985lili/articles/100450.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Sat, 24 Feb 2007 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/100450.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/100450.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/100450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/100450.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/100450.html</trackback:ping><description><![CDATA[&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />&lt;mx:Application xmlns:mx="<a href="http://www.adobe.com/2006/mxml" target="_blank">http://www.adobe.com/2006/mxml</a>" layout="vertical" creationComplete="initVars()" viewSourceURL="srcview/index.html"&gt;<br /><br />&lt;mx:Script&gt;<br />        &lt;![CDATA[<br />            import mx.rpc.events.ResultEvent;<br />            import mx.controls.Alert;<br />            import mx.collections.ArrayCollection;<br />            <br />        //holds all the records in the query returned by the CFC function     <br />        private var submissionsAllAryCol:ArrayCollection;<br />        <br />        //holds all the records in an Array<br />        //so we can use Array methods to <br />        //get a subset of the records for paging<br />        private var submissionsAllAry:Array;<br />        <br />        //The subset of the records for the current page<br />        private var submissionsSlicedAry:Array;<br />        <br />        //The subset of the records in the ArrayCollection<br />        //that is the dataprovider for the datagrid<br />        [Bindable]<br />        private var submissionsViewAryCol:ArrayCollection;<br />        <br />        [Bindable]<br />        private var start:int; //what record to start with on the current page<br />        <br />        private var increment:int ; //how many records to show per page<br />        <br />        [Bindable]<br />        private var end:int ; //what record (end-1) to end with on the current page<br />        <br />        [Bindable]<br />        private var total:int ; //how many total records<br />        <br />        <br />      <br />        <br />        // initialize the variables and get all submissions<br />        private function initVars():void {<br />            <br />            //initial start and end positions for slicing the Array<br />            start = 0;<br />            increment = 10; //how many records to display<br />            end = 0;<br />                    <br />           //Call the CFC method to get the submissions        <br />           myService.getAllSubmissions(139);<br />        <br />        }  //end function initVars()    <br />            <br />         /*Handles the result returned by calling the getAllSubmissions method<br />            of the CFC<br />            */<br />            public function handleQueryResult(event:ResultEvent):void{<br />                <br />                //place the query results into an ArrayCollection<br />                submissionsAllAryCol = event.result as ArrayCollection;<br />                <br />                //convert ArrayCollection to a standard Array<br />                //so we can use Array slice function<br />                submissionsAllAry = submissionsAllAryCol.toArray();<br />                <br />                //how many total submissions?<br />                total = submissionsAllAry.length;<br />                <br />                //determine initial value for end (cannot exceed total)<br />                <br />                if ( total &lt; increment) {<br />                    <br />                    end = total;<br />                    <br />                } else {<br />                    <br />                    end = increment ;<br />                    <br />                }//end if<br />                <br />                <br />                //take out of the array records start to end (includes records from start to end-1)<br />                submissionsSlicedAry = submissionsAllAry.slice(start, end);<br />                <br />                //Create an ArrayCollection using the subset of our Array<br />                //and assign it to the data provider for the datagrid<br />                submissionsViewAryCol = new ArrayCollection( submissionsSlicedAry );<br />                <br />                //determine if Next button should be enabled<br />                //as its possible that the number or records returned<br />                //is less than our number per page (increment)<br />                nextBtn.enabled = isNextBtnEnabled();<br />                <br />                    <br />            } //end function<br />                <br />            /*Get the next increment of records for display in the datagrid<br />            */<br />            private function getNext():void {<br />                <br />                //going forward so <br />                //increase start and end by the increment<br />                <br />                start = start + increment ;<br />                end = end + increment ;<br />                <br />                //don't let the value of end be larger than the<br />                //total number of records<br />                if (end &gt; total) {<br />                    <br />                    end = total;<br />                    <br />                }<br />                <br />                //create a subset of the Array that is holding all the submissions<br />                submissionsSlicedAry = submissionsAllAry.slice(start, end);<br />                <br />                //update the dataprovider for the datagrid<br />                submissionsViewAryCol = new ArrayCollection( submissionsSlicedAry );<br />                <br />                //determine if Next button should be enabled<br />                <br />                nextBtn.enabled = isNextBtnEnabled();<br />                <br />                //enable previous button<br />                //since we have gone to a next page of records<br />                previousBtn.enabled = true;<br />                <br />                <br />            }//end getNext<br />            <br />           <br />           /*Get the previous increment of records for display in the datagrid<br />           */<br />           private function getPrevious():void {<br />               <br />                 <br />                   //going backwards<br />                   end = start;<br />                <br />                //decrease start by the increment<br />                <br />                start = start - increment ;<br />                <br />                //create a subset of the Array that is holding all the submissions<br />                submissionsSlicedAry = submissionsAllAry.slice(start, end);<br />                <br />                //update the dataprovider for the datagrid<br />                submissionsViewAryCol = new ArrayCollection( submissionsSlicedAry );<br />                <br />                //determine if previous button should be enabled<br />                previousBtn.enabled = isPreviousBtnEnabled();<br />                <br />                //enable next button<br />                //since we have gone to a previous page of records<br />                nextBtn.enabled = true;<br />                <br />                <br />            }//end getPrevious<br />            <br />            /*Return true if button should be enabled<br />            */<br />            private function isNextBtnEnabled():Boolean {<br />                <br />                var enableBtn:Boolean = false ;<br />                <br />                if ( end &lt; total ) {<br />                    <br />                    enableBtn = true ;<br />                    <br />                }<br />                <br />                return enableBtn;<br />            <br />                <br />            }//end function isNextBtnEnabled<br />            <br />            <br />            /*Return true if button should be enabled<br />            */<br />            <br />            private function isPreviousBtnEnabled():Boolean {<br />                <br />                var enableBtn:Boolean = false ;<br />                <br />                if ( start &gt;= increment ) {<br />                    <br />                    enableBtn = true ;<br />                    <br />                }<br />                <br />                return enableBtn;<br />                <br />                <br />                <br />            }//end function isNextBtnEnabled<br />            <br />            <br />        ]]&gt;<br />&lt;/mx:Script&gt;            <br />            <br />    &lt;!--setup connection to the CFC--&gt;<br />    &lt;mx:RemoteObject<br />        id="myService"<br />        destination="ColdFusion"<br />        source="flex.pagingdatagrid.SubmissionsGateway" <br />        showBusyCursor="true"<br />        &gt;  <br />            &lt;mx:method name="getAllSubmissions" result="handleQueryResult(event)" <br />            fault="Alert.show(event.fault.message)"/&gt;<br />                <br />    &lt;/mx:RemoteObject&gt; <br />    <br />    &lt;!--setup user interface--&gt;<br />    &lt;mx:Panel width="80%" height="80%" layout="vertical" title="Page Through The Submissions" <br />        horizontalAlign="center" verticalAlign="top"&gt;<br />        <br />        &lt;mx:VBox width="100%" height="100%" verticalAlign="top" horizontalAlign="left"&gt;<br />        <br />        &lt;mx:Label text="Use the Previous and Next buttons to Get More Submissions"/&gt;<br />        <br />        &lt;mx:HBox width="100%"&gt;<br />            <br />            &lt;!--this button's enable value will be changed by the getPrevious() and getNext functions--&gt;<br />            &lt;mx:Button label="Previous" id="previousBtn" enabled="false" <br />                click="getPrevious()"/&gt;<br />                <br />            &lt;mx:Spacer width="50%"/&gt;<br />            <br />            &lt;!--must use start+1 since array elements start at array position 0--&gt;<br />            &lt;mx:Label text="Viewing Submissions {start+1} - {end} of {total} Submissions" /&gt;<br />            <br />            &lt;mx:Spacer width="50%"/&gt;<br />            <br />             &lt;!--this button's enable value will be changed by the getPrevious() and getNext functions--&gt;<br />            &lt;mx:Button label="Next" id="nextBtn" enabled="true"<br />                click="getNext()"/&gt;<br />            <br />        &lt;/mx:HBox&gt;<br />        <br />        &lt;!--The dataProvider will be updated each time the user clicks the next and previous buttons--&gt;    <br />        &lt;mx:DataGrid width="100%" height="100%" id="submissionsDG" dataProvider="{submissionsViewAryCol}" <br />            fontFamily="Verdana" fontSize="10"&gt;<br />            &lt;mx:columns&gt;<br />                &lt;mx:DataGridColumn dataField="submissionid" width="80" headerText="Sub #"/&gt;<br />            <br />                &lt;mx:DataGridColumn dataField="presenter" width="100" headerText="Main Presenter" /&gt;<br />                <br />                &lt;mx:DataGridColumn dataField="title" width="220" headerText="Title" wordWrap="true"/&gt;<br />            &lt;/mx:columns&gt;<br />        &lt;/mx:DataGrid&gt;<br />            <br />        &lt;/mx:VBox&gt;<br />        <br />    &lt;/mx:Panel&gt;<br /><br />   &lt;!--setup user interface--&gt;<br />&lt;/mx:Application&gt;<img src ="http://www.blogjava.net/19851985lili/aggbug/100450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-24 09:10 <a href="http://www.blogjava.net/19851985lili/articles/100450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 如何利用 google 查找 Flex 程序 </title><link>http://www.blogjava.net/19851985lili/articles/99131.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Sat, 10 Feb 2007 06:01:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/99131.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/99131.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/99131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/99131.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/99131.html</trackback:ping><description><![CDATA[网上有很多人提供了很多的 Flex 2 制作的程序，并且提供源代码供人查看，但是基本上都是在个人的博客中发表，查找起来很累，基本上是漫无目的溜。其实利用 google 可以很容易查找到各种源代码。<br />方法：源代码分为 mxml 和 as，而 mxml 文件中肯定包含 &lt;mx:Application xmlns:mx="<font size="-1">http://www.macromedia.com/2006/mxml"&gt; 这句话，因此，只要在搜索框中搜索“mx Application 2006 filetype:mxml”，所有的 Flex 2 代码一览无余。如果要搜 as 文件的话，搜索 "import mx filetype:as"，这个却容易找到一些 as2 的文件，美中不足...<br /></font><img src ="http://www.blogjava.net/19851985lili/aggbug/99131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-10 14:01 <a href="http://www.blogjava.net/19851985lili/articles/99131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cairngorm</title><link>http://www.blogjava.net/19851985lili/articles/98837.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Thu, 08 Feb 2007 10:00:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/98837.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/98837.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/98837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/98837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/98837.html</trackback:ping><description><![CDATA[
		<br />
		<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>主要就是对开发Flex应用程序应用了一系列的设计模式，从而使开发出来Flex程序可扩展性，可维护性都大大提高。其<a name="baidusnap1"></a><b style="COLOR: black; BACKGROUND-COLOR: #a0ffff">工作流程</b>很清晰：<br /><br />1.Front Controller Listens for User Gestures<br />前端的控件监听用户的行为。注意它只是监听，并不会做任何反应。<br /><br />2.Commands Do All the Work<br />控件监听以后调用Commands来做相应的事情，Command做了所有工作。<br /><br />3.Delegate Server-Side Business Logic to Business Delegates<br />把服务器端的业务逻辑委托到 Bussiness Delegates中。因为很多时候command需要获得服务器端数据，所以这样一来它可以直接调用Bussiness Delegates而不用关注如何连接数据的细节，实现了信息隐藏。<br /><br />4.Business Delegate Finds Services with the Service Locator<br />Command调用Business Delegate 后，Business Delegate 通过Service Locator来找到相应的RPC services，然后执行实现从服务器端取数据。<br /><br />5.Transfer Data as Value Objects<br />把传输过来的数据存储为Value Objects。这点大家应该都很熟悉，比如想要查询一个公告，就必定创建一个公告类，来存储每一个公告的标题等信息。<br /><br />6.Store State in the Model Locator and Let Model Notify View<br />在Model Locator 保存状态并且能使Model检测到View的变化。这样一来用户操作就能直接影响Model，比如添加物品到购物车，Model中的购物商品就会自动增加。<br /><img src ="http://www.blogjava.net/19851985lili/aggbug/98837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-08 18:00 <a href="http://www.blogjava.net/19851985lili/articles/98837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么要选择Cairngorm开发框架？</title><link>http://www.blogjava.net/19851985lili/articles/98310.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Tue, 06 Feb 2007 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/98310.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/98310.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/98310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/98310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/98310.html</trackback:ping><description><![CDATA[
		<div class="entryBody">
				<p>我是一个JAVA EE开发人员，从业已经有近七、八年的时间了。对JavaEE的企业用户开发技术框架方面的比较熟悉。对Spring，Struts，Webwork，Hibernate等流行的开源框架也一直在工作中使用。</p>
				<p>在现在的MVC框架中，我比较倾向于采用WebWork，灵活轻巧Struts2其实质就是对WebWork2的一次升级，这也说明了WebWork相对与Struts1的优势所在。在现在的RIA开发成为趋势之后，在工作中也使用了DWR做Ajax服务器端的数据处理，并采用js template的脚本处理页面显示数据，其中最大的痛苦就是调试JavaScript，尽管我们使用了firefox的插件调试javascrpt。</p>
				<p>正如“<a title="ria" href="http://realsky.blogbus.com/logs/2006/11/3810636.html" target="_blank">JAVA程序员当如何选择RIA开发环境</a>”所提到ajax的的先天缺陷，并不适合RIA的全应用开发，如果只是在页面中的局部使用是有一些优势，根据具体情况选择最合适的。</p>
				<p>在Flex的应用程序开发当中，学习了很对范例，基本上浏览了一遍Flex的帮助文档，并自己做了些小程序。</p>
				<p>其中遇到最大的困难不是在程序调试方面，而且程序管理方面的，代码混乱，难以控制，尤其在多人开发的时候，更加容易出现这样的情况。这样的情况下RIA的开发是痛苦的，不适宜的。</p>
				<p>
						<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>开发框架说白了就是一个FLEX应用开发的MVC框架（自己的感觉）。将Model，view，Control独立分开，清晰明了。<br /><br />什么是<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>？<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>是一个通过逻辑功能、数据、用户视图和代码控制的任何事情来划分你的应用程序代码的基础方法论，可以叫做MVC（Model-View-Control）的一种实践方式。</p>
				<p>
						<strong>
								<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>的划分</strong>
						<br />
						<strong>Model Locator（模型定位器）：</strong>存储你的应用中所有的Value Objects（数据）和共享变量在一个位置。和Http的Session对象类似，只是它存储在Flex接口的客户端而不是在中间件应用服务器的服务器端。</p>
				<p>
						<strong>View（界面）：</strong>通过一个或者多个Flex组件（按钮、面板、组合框、Tile等等）组合在一起的一个个命名单元，绑定数据在Model Locator（模型定位器）中，并且产生基于用户操作（点击、滚动、拖拽等）的自定义的<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>事件。</p>
				<p>
						<strong>Front Controller（前端控制器）：</strong>接收<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>事件并映射他们到<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>命令控制器上。</p>
				<p>
						<strong>Command（命令控制器）：</strong>处理商业逻辑，调用Caringorm代理和（或）其它命令。</p>
				<p>
						<strong>Delegate（代理）：</strong>由命令创建，实例化远程过程调用（HTTP、Web Service等等）并且处理命令的返回结果数据。</p>
				<p>
						<strong>Service（服务）：</strong>定义连接远程数据存储的远程过程调用（HTTP、Web Service等等）。<br /><br /><br />有关<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>的资料：/P&gt; <br /></p>
				<p>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: ">
								<font size="2">
										<font face="Verdana">
												<strong>
														<font style="BACKGROUND-COLOR: #ffff66">Cairngorm</font>
												</strong>是Iteration::two的开源项目, 是使用macromedia Flex的RIA开发的最佳<br />实践(best-practice)框架. <br />在<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>基础上开发RIA, 将会在Iteration::two的专家体系和现有的灵活可维<br />护企业解决方案中达到平衡.<br /><b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b>本身并不是一个完整的企业应用, 它只是提供了一个开发的骨架, Iteration::two称<br />之为体系.<br />在这个体系中包括以下几个部分:<br />1. Business(业务逻辑部分)<br />2. Command(命令部分)<br />3. Control(控制部分)<br />4. Model(数据模型)<br />5. View(界面视图)<br />6. VO(ValueObject)</font>
								</font>
								<font face="Times New Roman">
								</font>
						</span>
				</p>
				<p>
						<font face="verdana,arial,helvetica,sans-serif" size="2">我们从Control说起:<br />在Control中, 定义了3个基类: Event, EventBroadcaster, FrontController.<br />Event用于在应用不同的层之间传递事件, 并携带事件的数据. 包含type和data两个<br />成员. <br />type存放一个区别不同事件的名称,将会在FrontController中进行注册. <br />而在命令(Command)类中, 会对事件进行响应.</font>
				</p>
				<p>
						<font face="verdana,arial,helvetica,sans-serif" size="2">EventBroadcaster是一个单例类(singleton), 用于广播用户动作对应的事件. 使用<br />方法: EventBroadcaster.getInstance().broadcastEvent( ... )</font>
				</p>
				<p>
						<font face="verdana,arial,helvetica,sans-serif" size="2">FrontController稍微复杂一点点. 用于将特定的用户动作分发到指定的命令类. &#x14;<br />FrontConroller是请求处理的核心类. 整个体系中遍布的EventBroadcaster.getInstance(<br />).broadcastEvent( ... )这样的调用, <br />都是用来通知监听控制器: 用户发出了请求. 在实际应用中, 开发者应该生成一个<br />FrontContoller的子类, <br />并在构造函数中调用addCommand()注册预期事件的处理命令. FrontController的具<br />体实现类应该创建一次而且只能创建一次. <br /></font>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<a href="http://cairngormdocs.org/">
								<br />
								<br />http://cairngormdocs.org/</a>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: ">
								<a href="http://labs.adobe.com/wiki/index.php/Cairngorm">http://labs.adobe.com/wiki/index.php/<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">Cairngorm</b></a>
						</span>
				</p>
		</div>
<img src ="http://www.blogjava.net/19851985lili/aggbug/98310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-06 14:55 <a href="http://www.blogjava.net/19851985lili/articles/98310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>