自定义事件没有冒泡(或没有听到!)

时间:2013-09-09 09:40:44

标签: actionscript-3 flex flex3

我在调度事件时遇到了一些创伤,但我无法在主应用中检测到它。我已经敲了一个代码示例,删除多余的东西,所以它看起来有点不寻常!

我有一个主应用程序,(Air),它有一个带有单个按钮的画布。这个按钮打开一个PopUp标题窗口,里面有一个数据网格。在单击datagrid时,将调度一个非常简单的自定义事件,该事件在最低级别被听到,但不会调用canvas或主应用程序。我假设它是如何定义上层的听众,但它真的让我发疯!代码如下:

mainApp.mxml ..........

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" 
                                        layout="absolute"
                                        creationComplete="{onCreationComplete()}" 
                                        xmlns:components="components.*"
                                         >

<mx:Script>
    <![CDATA[

        import components.lowestLevel;

        private var lowest:lowestLevel;

        private  function onCreationComplete():void
        {
                 lowest = new lowestLevel;

                 lowest.addEventListener('myEventType',mainAppListenerHandler);

        }


        private function mainAppListenerHandler(event:Event):void
        {
            trace("ive been heard  in main app")
        }   

    ]]>

</mx:Script>

        <components:middleLevel/>

</mx:WindowedApplication>

middleLevel.mxml

<?xml version="1.0" encoding="utf-8"?>
    <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" 
                    width="900" 
                    height="50"
                    creationComplete="{ addEventListener('myEventType',listenerHandler);}"
                    >

    <mx:Script>
        <![CDATA[
            import mx.core.Application;
            import mx.managers.PopUpManager;
            import actionScript.sql;

            private function launchViewAllLoads(event:MouseEvent):void
            {            

                sql.getSourceFilesToView()

                var win:lowestLevel = new lowestLevel();

                PopUpManager.addPopUp(win,parent,true);
                PopUpManager.centerPopUp(win); 

            }

            private function listenerHandler(event:Event):void
            {
                trace("im heard at the Middle level" )      
            }           

]]>


    </mx:Script>

    <mx:Button  id="btnViewAllLoads"
                        label="View Current"
                        click="{launchViewAllLoads(event)};"
                         />

    </mx:Canvas>

lowestLevel.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="vertical" width="800" height="550"
    title="View All Loads" horizontalAlign="center"
    creationComplete="{ addEventListener('myEventType',listenerHandler);}"
      >

    <mx:Script>
        <![CDATA[

            import mx.core.IFlexDisplayObject;
            import mx.events.CloseEvent;
            import mx.managers.PopUpManager;


            private function listenerHandler(event:Event):void
            {
                trace("im heard at the lowest level" )      
            }


            private function sourceFilesToViewClickedHandler():void
            {   
                PopUpManager.removePopUp(this as IFlexDisplayObject);

                var myEvent:Event = new Event('myEventType' ,true,true);
                dispatchEvent(myEvent); 

            }

        ]]>
    </mx:Script>

        <mx:Canvas  id="cSourceFiles" width = "100%" height="100%">

                <mx:DataGrid    id="dgSourceFiles"  
                                        click="{sourceFilesToViewClickedHandler()}">

                <mx:columns>
                    <mx:DataGridColumn dataField="Batch"  headerText="Batch" width="80"/>
                    <mx:DataGridColumn dataField="LastUpdated"  headerText="Last Updated" width="85"/>                                  
                </mx:columns>

            </mx:DataGrid>


        </mx:Canvas>
</mx:TitleWindow>

2 个答案:

答案 0 :(得分:0)

如果您重新发送同一事件该怎么办:

private function listenerHandler(event:Event):void {
    trace("im heard at the Middle level" )      
    dispatchEvent(event);
}

使用回调:

var callback = function():void {
   // do some stuff here
}
lowest = new lowestLevel(callback);

之后,而不是发送事件:

private var _callback:Function;
public function lowestLevel(callback:Function):void {
  _callback = callback;
}
private function sourceFilesToViewClickedHandler():void {   
  PopUpManager.removePopUp(this as IFlexDisplayObject);
  _callback();
}

答案 1 :(得分:0)

我在这里看到一些问题。首先是你的mainApp.mxml:

private  function onCreationComplete():void
{
         lowest = new lowestLevel;

         lowest.addEventListener('myEventType',mainAppListenerHandler);

}

您正在创建lowestLevel的实例并向其添加事件侦听器。但是,这与middleLevel中创建的实例不同。如果您有一个组件的两个独立实例;在一个实例中调度事件不会导致另一个实例上的事件侦听器触发。

由于您的mainApp的lowestLevel实例从未以任何方式添加到舞台中;用户永远不会与事件进行交互。

你可以试试这个:

private  function onCreationComplete():void
{
         this.addEventListener('myEventType',mainAppListenerHandler);
}

这将在mainApp文件中添加事件侦听器。随着事件泡沫;在显示层次结构中的每个类上调度该事件。所以,这应该工作。

我看到的第二个问题是PopUpManager将其窗口创建为SystemManager组件的子窗口;它独立于当前的显示层次结构。引用docs

  

所有弹出窗口都是SystemManager的父级。

因此,从lowestLevel调度事件不会冒泡到middleLevel或mainApp,因为它实际上不是“最低级别”。它几乎就像它存在于并行层次结构中一样。

解决方案是直接在middleLevel中的lowestLevel实例上侦听事件并重新发送它。