2009-04-23 10 views
1

J'ai une liste avec un ItemRenderer personnalisé. ItemRenderer contient une case à cocher et un libellé. Le composant avec la liste a une case à cocher 'Sélectionner tout'. Lorsque la case à cocher «Sélectionner tout» est cochée, elle distribue un événement que chaque élément doit écouter pour sélectionner sa propre case à cocher. L'événement eventlistener est ajouté lors de la créationComplete de chaque élément et l'événement est distribué correctement lorsque la case à cocher 'select all' est sélectionnée, mais que l'écouteur du ItemRenderer personnalisé n'écoute pas.Flex3: Le rendu d'élément personnalisé n'écoute pas les événements distribués par le parent

Comment faire pour que ItemRenderer écoute un événement distribué dans son parent?

Je vais ajouter quelques exemples de code pour clarifier:

------- 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> 

S'il vous plaît noter que les utilisateurs ArrayCollection ou ses objets utilisateur contenant ne peuvent pas être modifiés parce que je besoin des valeurs plus tard. Ainsi, lorsque vous cliquez sur 'selectAll', chaque case de la liste doit également être cochée.

Répondre

2

Votre ItemRenderers personnalisés ne devraient pas enregistrer un écouteur d'événement avec leurs parents, mais avec votre case à cocher « tout sélectionner », à savoir

theCheckbox.addEventListener(YourEvent.YOUR_EVENT, itemRendererSelectAllHandler); 

A défaut, vous pouvez poster votre code qui ajoute l'écouteur d'événement et qui envoie l'événement forme la case à cocher?

modifier:

Voici votre bug: Dans init renderer(), vous devez ajouter un écouteur d'événement à ne pas le moteur de rendu, mais au conteneur qui distribue l'événement. Donc faire un

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

Faire tout sélectionner dans flex est un peu complexe mais je vais vous dire la façon dont nous l'avons fait et cela fonctionne très bien.

Nous avons créé un contrôle dérivé de liste appelé "ExList" qui a une propriété "selectAllCB" que nous lions à la case à cocher existante qui fonctionnera pour sélectionner toute la logique. Notez que lorsque nous définissons la propriété selectAllCB, ExList écoute les événements de la case à cocher.

Lorsque cette case est cochée, nous définissons manuellement arrayItems array sur array of dataProvider et tous les éléments sont sélectionnés.

Jouer avec itemRenderer ne fonctionne pas correctement car lorsque vous programmez votre liste encore et encore chaque fois que vous devez écrire autant de code.

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(); 
      } 
     } 
} 

Et vous pouvez l'utiliser comme ...

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

// Please note its in curly braces 
0

Voici comment j'ai réalisé la 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> 
0

La solution simple consiste à utiliser des objets saisis dans la liste des les données que vous présentez, puis profitez de la liaison de données et des utilitaires de liaison pour capturer les modifications de la propriété de données sous-jacente sur le rendu d'élément. Remplacez la fonction 'set data' dans le renderer d'élément pour faire ce dont vous avez besoin quand une propriété de l'objet est modifiée pour refléter l'état 'select all/de select all'.