简体   繁体   English

Flex3:自定义项目渲染器不侦听父级调度的事件

[英]Flex3: Custom Item Renderer does not listen to events dispatched by parent

I have a List with a custom ItemRenderer. 我有一个带有自定义ItemRenderer的列表。 The ItemRenderer contains a Checkbox and a Label. ItemRenderer包含一个复选框和一个标签。 The component with the List has a 'select all' checkbox. 具有列表的组件具有“全选”复选框。 When the 'select all' checkbox is checked, it dispatches an event that each item should listen to in order to select its own checkbox. 选中“全选”复选框后,它将调度一个事件,每个项目都应侦听以便选择自己的复选框。 The eventlistener is added on creationComplete of each item, and the event is dispatched correctly when the 'select all' checkbox is selected, but the listener in the custom ItemRenderer does not listen. 将eventlistener添加到每个项目的creationComplete上,并且在选中“全选”复选框时会正确调度该事件,但是自定义ItemRenderer中的侦听器不会侦听。

How do I make the ItemRenderer listen to an event that is dispatched in its parent?? 如何使ItemRenderer侦听在其父级中调度的事件?

I'll add some code examples to clarify: 我将添加一些代码示例来阐明:

------- container ----------
<mx:VBox>
   <mx:Script>
      <![CDATA[
         public var user1 = new User(1, "Jack");
         public var user2 = new User(2, "John");
         public var user3 = new User(3, "Mary");

         [Bindable]
         public var users:ArrayCollection = new ArrayCollection([user1], [user2], [user3]);

         public static const SELECT_ALL_USERS:String = "selectAllUsers";

         private function selectAllChangeHandler():void
         {
            if (selectAll.selected)
               dispatchEvent(new Event(SELECT_ALL_USERS,true));
         }
      ]]>
   </mx:Script>
   <mx:CheckBox id="selectAll" change="{selectAllChangeHandler()}" />
   <mx:List dataProvider="{users}" itemRenderer="myRenderer" />
</mx:VBox>


------- renderer ----------
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox creationComplete="{init()}">
   <mx:Script>
      <![CDATA[
         private function init():void
         {
            addEventListener (Container.SELECT_ALL, selectAllHandler, false, 0, true);
         }

         private function selectAllHandler():void
         {
            checkbox.selected=true;
         }

         private function selected(id:int):Boolean
         {
             return id==1 || id==3;
         }
      ]]>
   </mx:Script>

   <mx:CheckBox id="checkbox" selected="{selected(data.id)}" />
   <mx:Label text="{data.name}" />
</mx:HBox>

Please note that the users ArrayCollection or its containing user objects cannot be changed because I need the values later on. 请注意,用户ArrayCollection或其包含的用户对象无法更改,因为稍后需要这些值。 So when 'selectAll' is clicked, each checkbox in the list should also be checked. 因此,当单击“ selectAll”时,也应选中列表中的每个复选框。

Your custom ItemRenderers should not register an event listener with their parent, but with your "select all" checkbox, ie 您的自定义ItemRenderer不应在其父级中注册事件监听器,而应在“全选”复选框中注册,即

theCheckbox.addEventListener(YourEvent.YOUR_EVENT, itemRendererSelectAllHandler);

Failing that, can you post your code which adds the event listener and which dispatches the event form the checkbox? 如果失败,您是否可以发布添加事件侦听器并从复选框分派事件的代码?

edit: 编辑:

Here's your bug: In renderer's init(), you need to add an event listener not to the renderer, but to the container which dispatches the event. 这是您的错误:在渲染器的init()中,您需要向添加事件的容器添加事件侦听器,而不是将其添加到渲染器。 So make that a 因此,使一个

container.addEventListener(Container.SELECT_ALL_USERS, selectAllHandler, false, 0, true);

Doing select all in flex is little complex but I will tell you the way we did it and it works great. 在flex中进行全选并不复杂,但是我将告诉您我们的操作方式,并且效果很好。

We created a List derived control called "ExList" which has a property "selectAllCB" which we bind it to existing check box which will work for select all logic. 我们创建了一个名为“ ExList”的列表派生控件,该控件具有属性“ selectAllCB”,将其绑定到现有复选框,该复选框适用于选择所有逻辑。 Please note, when we set selectAllCB property, we make ExList to listen to checkbox's events. 请注意,当我们设置selectAllCB属性时,我们使ExList监听复选框的事件。

When checkbox is checked, we manually set selectedItems array to array of dataProvider and all items are selected. 选中复选框时,我们将selectedItems数组手动设置为dataProvider的数组,并且所有项目均被选中。

Playing with itemRenderer doesnt work correctly because when you program your list again and again everytime you have to write so much of code. 使用itemRenderer不能正常工作,因为当您一次又一次地对列表进行编程时,每次必须编写大量代码。

I am attaching some sample code here below..

    public class ExList extends List 
    {
        public function ExTileList()
        {
            super();
            this.allowMultipleSelection = true;
        }

        private var _selectAllCB:CheckBox = null;
        [Bindable]
        public function get selectAllCB():CheckBox
        {
            return _selectAllCB;
        }
        public function set selectAllCB(v:CheckBox):void
        {
            if(v==null)
                return;
            _selectAllCB = v;
            v.addEventListener(ListEvent.ITEM_CLICK, handleAllChange,false, 0 , true);
            v.addEventListener("change", handleAllChange,false, 0 , true);
        }

        private function handleAllChange(e:Event):void
        {
            if(_selectAllCB.selected)
            {
                this.selectedItems = this.dataProvider.toArray();
            }
            else
            {
                this.selectedItems = new Array();
            }
        }
}

And you can use it as... 您可以将其用作...

<CheckBox id="sAll"/>
<ExList selectAllCB="{sAll}"/>

// Please note its in curly braces

This is how I achieved the solution: 这是我实现解决方案的方式:

    <?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" height="150" verticalGap="0">
    <mx:Script>
 <![CDATA[
         import mx.events.ListEvent;
  import mx.controls.CheckBox;
  import mx.collections.ArrayCollection;

  public var listData:ArrayCollection;

  private function selectAll():void
  {
   listChkBox.selectedItems = listData.toArray();
   for each (var item:Object in listChkBox.selectedItems)
   {
    CheckBox(listChkBox.itemToItemRenderer(item)).selected = true;
          }   
  }

  private function resetAll():void
  {
   listChkBox.selectedItems = listData.toArray();
   for each (var item:Object in listChkBox.selectedItems)
   { 
                         CheckBox(listChkBox.itemToItemRenderer(item)).selected = false;
   } 
  }


  ]]>
 </mx:Script>
 <mx:List width="100%" height="100%" id="listChkBox" labelField="name" allowMultipleSelection="true"
   dataProvider="{listData}"  selectionColor="#FFFFFF" >
  <mx:itemRenderer>
   <mx:Component>
    <mx:CheckBox >
    </mx:CheckBox>
   </mx:Component>
  </mx:itemRenderer>
 </mx:List>
 <mx:HBox width="100%"  backgroundColor="#E2DEDE" paddingBottom="2" paddingLeft="2" paddingTop="2" paddingRight="2" borderStyle="solid">
  <mx:Button label="All"  id="btnAll" click="selectAll()" />
  <mx:Button label="None" click="resetAll()"/>
 </mx:HBox>
</mx:VBox>

The simple solution is to use typed objects in the list of data you are presenting and then take advantage of databinding and the binding utils to capture changes to the underlying data property on the item renderer. 一种简单的解决方案是在要显示的数据列表中使用类型化的对象,然后利用数据绑定和绑定实用程序来捕获对项目渲染器上基础数据属性的更改。 Override the 'set data' function in the item renderer to do whatever you need when some property in the object gets changed to reflect the 'select all/de select all' state. 当对象中的某些属性发生更改以反映“全选/全选”状态时,重写项目渲染器中的“设置数据”功能以执行所需的任何操作。

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

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