Flex DataGrid – Sélection de lignes dans un Datagrid avec des Checkbox
Tutorial Flex écrit par Vincent Le Gallic (www.frianbiz.com). Publiez vous aussi sur flex-tutorial!
Un Datagrid supporte par défaut la multi-sélection grâce à la propriété allowMultipleSelection. Cependant l’utilisation du Ctrl+click pour sélectionner plus d'un item à la fois n’est pas toujours adaptée. Comme dans l’interface de Gmail (réputée conviviale et pratique) la multi sélection peut être gérée grâce à une case à cocher attribuée à chaque item de la liste. Voici une façon de mettre en place cette technique en Flex :
Tous les objets affichés dans le Datagrid doivent avoir une propriété qui vous permettra de savoir si la ligne est sélectionnée ou pas. Dans l’exemple ci-dessous cette propriété se nomme « selected »
<mx:Object songId="0" title="Astronaut" artist="David Byrne" selected="false"/>
Cette propriété est fixée et utilisée directement dans la donnée car les itemRenderer que l'on va utiliser ensuite ont un mécanisme de recyclage. Il nous faut donc un emplacement où garder cette valeur en mémoire. La donnée remplit parfaitement ce rôle.
Pour commencer il faut ajouter une colonne au Datagrid qui contiendra un inline item renderer. On peut ensuite ajouter notre Checkbox. La propriété selected de la Checkbox (qui définit si notre case est cochée ou pas) sera liée à la propriété selected des items du datagrid de la façon suivante :
<mx:CheckBox selected="{data.selected}"/>
Il faut ensuite écouter les changements d’état lorsqu’on clic sur la checkBox :
<mx:CheckBox selected="{data.selected}" click="{data.selected=!data.selected}"/>
On met à jour la propriété selected de l’item afin d’éviter tout affichage aléatoire du à l’utilisation d’un itemRenderer dans un Datagrid.
En plus de cela, on va ajouter à notre application une liste des éléments sélectionnés.
En même temps que le basculement de la valeur de data.selected, on informe aussi notre application qu'un changement a été effectué. Pour cela, il faut passer par outerDocument car on se trouve dans un itemRenderer qui a son propre scope:
<mx:CheckBox label="" selected="{data.selected}" click="{data.selected=!data.selected;outerDocument.onItemChanged(data)}"/>
Pour plus d'explications sur ces échanges application/item renderer, vous pouvez consulter cet article:
Flex Item Renderer - Item Renderer utilisant des composants personnalisés MXML (Inline)
Au click sur la CheckBox, on appelle une méthode onItemChanged(event), qui va mettre à jour la liste des éléments sélectionnés. On met à jour les données du dataProvider à chaque modification pour éviter de boucler sur le dataProvider de notre DataGrid lorsque l’on souhaite récupérer toutes les lignes sélectionnées.
On ajoute aussi à notre application, une CheckBox permettant de sélectionner/déselectionner tous les éléments, simplement en bouclant sur les éléments du dataProvider et en fixant la propriété selected à true ou false. On appelle ensuite la méthode refresh() de la classe ArrayCollection pour mettre à jour le visuel.
Ci-dessous un exemple complet:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
import mx.controls.CheckBox;
import mx.collections.ArrayCollection;
[Bindable]
public var listeItemSelected : ArrayCollection = new ArrayCollection;
public function cbAllHandler(evt : Event):void{
listeItemSelected.removeAll();
for each (var item:Object in dp){
item.selected = cbAll.selected;
if(item.selected){
listeItemSelected.addItem(item);
}
}
dp.refresh();
}
public function onItemChanged(item : Object):void{
//Si l'item n'est pas déja dans la liste
if(listeItemSelected.getItemIndex(item)==-1) {
//on l'ajoute
listeItemSelected.addItem(item);
}else{
listeItemSelected.removeItemAt(listeItemSelected.getItemIndex(item)); //sinon on le supprime
}
}
]]>
</mx:Script>
<mx:ArrayCollection id="dp">
<mx:Array>
<mx:Object songId="0" title="Astronaut" artist="David Byrne" selected="false"/>
<mx:Object songId="1" title="Rio" artist="Duran Duran" selected="false"/>
<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" selected="false"/>
<mx:Object songId="3" title="Mesopotamia" artist="B-52s" selected="false"/>
</mx:Array>
</mx:ArrayCollection>
<mx:HBox>
<mx:VBox width="100%" height="100%">
<mx:CheckBox id="cbAll" label="{(cbAll.selected)?'tout décocher':'tout cocher'}" change="cbAllHandler(event)"/>
<mx:DataGrid dataProvider="{dp}" y="26" height="142">
<mx:columns>
<mx:DataGridColumn width="25" paddingLeft="5" paddingRight="5">
<mx:itemRenderer>
<mx:Component>
<mx:CheckBox label="" selected="{data.selected}" click="{data.selected=!data.selected;outerDocument.onItemChanged(data)}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Titre" dataField="title"/>
<mx:DataGridColumn headerText="Artist" dataField="artist"/>
</mx:columns>
</mx:DataGrid>
<mx:Label text="{dp.length+' résultat(s) '+listeItemSelected.length+' item(s) sélectionné(s)' }" />
</mx:VBox>
<mx:List labelField="title" dataProvider="{listeItemSelected}" height="142"></mx:List>
</mx:HBox>
</mx:Application>
Flex Source Code Download: Télécharger le code source complet de l'application
Articles similaires
- Flex Item Renderer – Item Renderer utilisant les composants Flex standard (Drop-In)
- Flex Item Renderer – Item Renderer utilisant des composants personnalisés MXML (Inline)
- Flex Item Renderer – Utiliser la propriété itemEditor pour la mise à jour
- Flex Item Renderer – Créer un ItemRenderer réutilisable avec listData
- Flex Drag And Drop – Drag And Drop natif avec dragEnabled et dropEnabled
Aucun trackbacks pour l'instant






21 septembre 2009
Bonjour,
Magnifique utilitaire, et très clairement expliqué, merci à Vincent Le Gallic. J'ai intégré avec succès ce code dans une application de calendrier partagé que je développe pour mon école.
Je cherche à ajouter une petite fonctionnalité supplémentaire depuis quelques jours, mais je n'y arrive pas. Peut-être l'auteur (ou quelqu'un-e d'autre) pourrait-il(elle) m'aider.
En fait, au chargement de mon application, une requête (php/amfphp/mySql) remplit la liste 'listeItemSelected' avec des informations (événement createComplete). Du coup, j'ai déjà des éléments dans cette liste dès le départ, avant que l'utilisateur puisse cocher ou décocher à volonté. Dès lors, je souhaiterais que les cases à cocher correspondantes aux éléments chargés s'activent dans la DataGrid au démarrage de l'application, mais je n'arrive pas à pointer sur les checkbox car elles n'ont pas d'identifiant. Pour prendre l'exemple de l'article ci-dessus, c'est comme si 'Duran Duran' et 'Depeche Mode' était chargé dans la liste 'listeItemSelected' au chargement de l'appli et que cela déclenchait la mise sur "true" des checkbox correspondantes dans la DataGrid 'dp'.
Merci mille fois de vos idées et propositions de solutions.
Alain
21 septembre 2009
Bonjour,
si dans votre donnée, la valeur "selected" de chaque objet est déjà fixée (à true ou à false), les checkbox sera initialisée dans le bon état grâce au Binding (selected="{data.selected}"). non?
Fabien
23 septembre 2009
Bonjour Fabien,
Bravo pour votre blog, c'est une mine d'or, et merci pour votre réponse.
En fait, mon problème venait du fait que ma DataGrid (nourrie par une ArrayCollection formée à partir d'une requête php/mysql) ne contenait pas de champ 'selected'. Grâce à votre remarque, j'ai pu cerner le problème... et l'ai résolu en bouclant le tableau source à l'intérieur du tableau contenant les checkbox
Merci encore mille fois et meilleures salutations.
Alain
28 mai 2010
Bonjour,
J'ai fais un datagrid avec des checkbox mais d'une manière un peu differente de la votre. En fait, je récupère les données d'une BDD que j'affiche dans mon grid, mais je n'ai pas de champ selected dans mes données pour gérer la checkbox. Quand, je coche un element de mon datagrid, je l'enregistre dans une liste (listElementsSelectionnes) et inversement. Et quand, je sauvegarde mes elements modifiés en base, je vide cette liste. Et ce que je voudrais aussi faire c'est reinitialiser les checkbox cochées de mon datagride à décochées mais je n'y arrive pas.
Voici mon code :
Merci,
Jeremy.
25 août 2011
Bonsoir,
Tout d'abord je voudrai vous remercier pour votre travail. Grâce a vous je ne suis paniqué lorsque je suis bloqué avec Flex. Voilà je voudrais savoir comment faire pour mettre un datagrid ayant une grande largeur dans un conteneur (un bordercontener de préférence) de largeur plus petite. Merci d'avance.
25 août 2011
J'ai oublier de mentionner que le conteneur en question aura alors un scroller horizontal ( chose que je ne sait pas faire)