简体   繁体   English

从Flex 4中的项目渲染器调用自定义事件

[英]call a custom event from an item renderer in flex 4

I have a Renderer: 我有一个渲染器:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                xmlns:mx="library://ns.adobe.com/flex/mx">

  <fx:Metadata>
    [Event(name="addToCart",type="event.ProductEvent")]
  </fx:Metadata>
  <fx:Script>
    <![CDATA[
      import events.ProductEvent;

      import mx.collections.ArrayCollection;


      protected function button1_clickHandler(event:MouseEvent):void
      {
        var eventObj:ProductEvent=new ProductEvent("addToCart",data.price,data.descript);

        dispatchEvent(eventObj);

      }
    ]]>
  </fx:Script>

  <fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
  </fx:Declarations>

  <s:states>
    <s:State name="normal"/>
    <s:State name="hovered"/>
  </s:states>

  <s:BorderContainer >
    <s:layout>
      <s:VerticalLayout paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"/>
    </s:layout>

    <s:Label text="{data.descript}"/>
    <mx:Image source="{data.url}" width="50" height="50" width.hovered="100" height.hovered="100"/>
    <s:Label text="{data.price}"/>
    <s:Button includeIn="hovered" click="button1_clickHandler(event)" label="buy"/>



  </s:BorderContainer>
</s:ItemRenderer>

and the custom event class: 和自定义事件类:

package events
{
  import flash.events.Event;
  [Bindable]
  public class ProductEvent extends Event
  {

    public var price:String;
    public var descript:String;

    public function ProductEvent(type:String,price:String, descript:String)
    {
      super(type);
      this.price=price;
      this.descript=descript;
    }
    override public function clone():Event
    {
      return new ProductEvent(type,price,descript);

    }
  }
}

but i cannot call that event in a container from the main application 但是我不能从主应用程序在容器中调用该事件

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal"   >
    <s:layout>
      <s:TileLayout/>
    </s:layout>

  </s:SkinnableDataContainer>

any ideas? 有任何想法吗?

thanks 谢谢


I want to make this: 我要这样做:

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" ***addToCart=something(event)*** >

Events are not called, so I'm not entirely sure what you want. 没有调用事件,所以我不确定您想要什么。

You can create an instance of an event class, like this: 您可以创建事件类的实例,如下所示:

var myProductEvent : ProductEvent  = new ProductEvent("productEventTypeA", true, ...); // true is for enabling Bubbles, so that the event bubbles up to the listener.

You can dispatch that event from an itemRenderer the same way you would do so if you were using an event elsewhere: 如果您在其他地方使用事件,则可以按照与发送事件相同的方式从itemRenderer调度该事件:

dispatchEvent(myEvent); 

Also on the item renderer, declare the event that is going to be dispatched: 同样在项目渲染器上,声明将要分派的事件:

[Event(name="productEventTypeA", type="local.events.ProductEvent")]

You can add an event listener on the List or DataGroup component implementing your item renderer so it runs your code after the event is dispatched: 您可以在实现项目渲染器的List或DataGroup组件上添加事件侦听器,以便在调度事件后运行代码:

myList.addEventListener("productEventTypeA", onProductEvent); // or a constant instead of "productEventTypeA"

or 要么

myDataGroup.addEventListener("productEventTypeA", onProductEvent); // or a constant instead of "productEventTypeA"

And finally declare your listener function in the same file you added the event listener: 最后,在添加事件侦听器的同一文件中声明您的侦听器功能:

public function onProductEvent(e:ProductEvent):void
{
// do stuff
}

Note : In an itemRenderer, you often want to make your event bubble so that it can be listened to on the component which uses renderers--usually a list based class. 注意 :在itemRenderer中,您通常希望使事件冒泡,以便可以在使用渲染器的组件(通常是基于列表的类)上侦听事件。

I hope this helps someone, you don't need to do all that... 我希望这对某人有帮助,您不需要做所有的事情...

It's very simple: 很简单:

ItemRenderer: ItemRenderer的:

protected function dispatchMyCustomEvent():void {
(owner as List).dispatchEvent(new CustomEvent);
}

if the parent isn't a list then just typecast it to what the parent is. 如果父级不是列表,则将其类型转换为父级。

then in your component that has the list you can do the following: 然后在具有列表的组件中,您可以执行以下操作:

protected function creationComplete():void {
myList.addEventListener(CustomEvent.TYPE, onMyCustomeEvent);
}

protected function onMyCustomEvent(event:MyCustomEvent):void {
// handle the event
}

It's hard to make out what you're trying to do from the question, because of the formatting, and it appears there's some text missing. 由于格式问题,很难从问题中找出要执行的操作,并且似乎缺少一些文本。

However. 然而。 try making the event bubble, and add the event listener on the list which holds the itemRenderers. 尝试使事件冒泡,并在包含itemRenderers的列表上添加事件侦听器。

Eg: 例如:

 <mx:Canvas creationComplete="list1.addEventListener('addToCart',onAddToCart)">
    <mx:List id="list1" itemRenderer="com.foo.YourItemRenderer" />
 </mx:Canvas>


 <!-- YourItemRenderer.mxml -->
 <mx:Canvas>
      <!-- Other item renderer stuff -->
       <mx:Button click="dispatchEvent(new ProductEvent('addToCart'))" />
 </mx:Canvas>


 // ProductEvent.as
 public class ProductEvent {
    public function ProductEvent(type:String,bubbles:Boolean=true) {
         super(type,bubbles);
         // ... etc
    }
 }

Perhaps this is a little out of scope, but that sort of signaling with events is where MVC frameworks like Cairngorm shine. 也许这有点超出范围,但是带有事件的信号传递正是Cairngorm之类的MVC框架大放异彩的地方。 I usually think of them as AS event buses. 我通常将它们视为AS事件总线。

This is possible using the Event metadata tag: http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html 使用事件元数据标记可以实现: http : //livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html

You'll have to sub-class SkinnableDataContainer and add the metadata tag: 您必须将SkinnableDataContainer子类化,并添加元数据标签:

[Event(name="addToCart", type="events.ProductEvent")]
public class MySkinnableDataContainer extends spark.components.SkinnableDataContainer
{
}

You can also do it in MXML: 您也可以在MXML中执行此操作:

<?xml version="1.0"?>
<!-- ../MySkinnableDataContainer.mxml -->
<s:SkinnableDataContainer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Script>
    <![CDATA[
        import events.ProductEvent;
    ]]>
    </mx:Script>

    <mx:Metadata>
        [Event(name="addToCart", type="events.ProductEvent")]
    </mx:Metadata>

</s:SkinnableDataContainer>

Then use this new class instead of the SkinnableDataContainer : 然后使用这个新类代替SkinnableDataContainer

<MySkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" addToCart="something(event)" />

Note: depending on your events bubble property you may have to catch it and then re-forward it along inside of MySkinnableDataContainer . 注意:根据事件的气泡属性,您可能必须捕获它,然后在MySkinnableDataContainer内部将其重新转发。

Make the event bubble: 使事件冒泡:

public function ProductEvent(type:String,price:String, descript:String)
{
  super(type, true); // Add bubbles = true instead of default false
  this.price=price;
  this.descript=descript;
}

Then in your app: 然后在您的应用中:

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" creationComplete="Sk.addEventListener('addToCart', myFunctionToHandle)">

Add an event listener on creation complete. 创建完成后添加事件侦听器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM