Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Flex Datagrid - Item Renderer et Item Editor - Exemples pratiques

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Compatible Flex 3. Cliquer pour en savoir plus sur les compatibilités.Par nico_d (Nico.), le 30 janvier 2011

Flex permet via des ItemRenderer de personnaliser de nombreux composants : List, HorizontalList, ComboBox…

Nous allons essayer ici de modifier le rendu du composant Flex DataGrid pour afficher des couleurs de texte et de fond différentes selon les données de chaque ligne:

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Puis nous afficherons dans la première colonne une case à cocher et nous essayerons de récupérer les modifications de cette case par l'utilisateur en utilisant la propriété Editable du datagrid.

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Les Item Renderer et Item Editor sont un vaste sujet. Cette page vous permettra d'essayer rapidement quelques cas de figure simples.
Pour aller plus loin, voyez le chapitre En savoir plus.

Rendu de base du DataGrid

Débutons ce tutoriel en ajoutant un composant Flex DataGrid dans notre application :

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  height="200" width="350">
	<mx:DataGrid height="200" width="350">
		<mx:columns>
			<mx:DataGridColumn headerText="Type" dataField="Type"/>
			<mx:DataGridColumn headerText="Marque" dataField="Marque"/>
			<mx:DataGridColumn headerText="Couleur" dataField="Couleur"/>
		</mx:columns>
	</mx:DataGrid>

Un Datagrid c'est beau, avec des données c'est mieux ! Ajoutons donc dans une balise script de notre code des données dans une ArrayCollection.

	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			[Bindable] private var mesDonnees_AC:ArrayCollection = new ArrayCollection([
				{Type:"Voiture", Marque:"Renault", 
					Couleur:"Rouge", activation:true, prix:80000}, 
				{Type:"Voiture", Marque:"Renault", 
					Couleur:"Vert", activation:false, prix:35000},  
				{Type:"Voiture", Marque:"Peugeot", 
					Couleur:"Jaune", activation:false, prix:22300},  
				{Type:"Voiture", Marque:"Citroen", 
					Couleur:"Orange", activation:false, prix:20000},  
				{Type:"Moto", Marque:"Honda", 
					Couleur:"Rouge", activation:false, prix:20000}, 
				{Type:"Moto", Marque:"Honda", 
					Couleur:"Rouge", activation:false, prix:30000},  
				{Type:"Moto", Marque:"Yamaha", 
					Couleur:"Rouge", activation:true, prix:3000},  
				{Type:"Moto", Marque:"Yamaha", 
					Couleur:"Rouge", activation:false, prix:1200} ]);
 
		]]>
	</mx:Script>

Et ajoutons au composant Datagrid le DataProvider cette façon :

<mx:DataGrid height="200" width="350" dataProvider="{mesDonnees_AC}">
		<mx:columns>
			<mx:DataGridColumn headerText="Type" dataField="Type"/>
			<mx:DataGridColumn headerText="Marque" dataField="Marque"/>
			<mx:DataGridColumn headerText="Couleur" dataField="Couleur"/>
			<mx:DataGridColumn headerText="Prix" dataField="prix"/>
		</mx:columns>
</mx:DataGrid>

Modifier la couleur de fond

Nous souhaitons mettre en évidence certaines valeurs de notre Datagrid en fonction d'un critère. Nous allons pour cela utiliser la propriété ItemRenderer du composant Datagrid. Nous allons donc créér une classe nommée “MonRenderer.as” avec le code ci-dessous dans le dossier renderer par exemple(.\src\renderer):

package renderer
{
	import flash.display.Graphics;
	import mx.controls.DataGrid;
	import mx.controls.Label;
	import mx.controls.dataGridClasses.*;
 
	public class MonRenderer extends Label
	{		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			//pour le background;
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			var g:Graphics = graphics;
			g.clear();
 
			var grid1:DataGrid = DataGrid(DataGridListData(listData).owner);
 
			if (uint(data.prix<10000))
			{
				g.beginFill(0x99cc99);
				g.drawRect(0, 0, unscaledWidth, unscaledHeight);
				g.endFill();
			}
 
		} 
	}
}

En utilisant extends Label nous héritons de la Super-Classe Label afin de pouvoir accéder aux méthodes et propriétés de cette classe.

Afin d'utiliser notre propre fonction d'affichage nous utilisons le mot clé Override dans la fonction updateDisplayList en utilisant la même signature que la fonction d'origine :

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void

Regardons plus en détail cette partie de code :

if (uint(data.prix<10000))  
{
  g.beginFill(0x99cc99);  
  g.drawRect(0, 0, unscaledWidth, unscaledHeight); 
  g.endFill();
}

Nous vérifions si la valeur présente dans la colonne prix de notre DataGrid est inférieure à 10000. (data.prix<10000).

Si c'est le cas le remplissage de la cellule commence avec une magnifique couleur verte (0x99cc99).

Débuggons a présent notre application pour constater que rien n’a changé !

Cela est tout à fait normal car notre datagrid utilise toujours le rendu de base.

Modifions cela dès à présent dans notre datagrid :

<mx:DataGrid height="200" width="350" dataProvider="{mesDonnees_AC}">
	<mx:columns>
		<mx:DataGridColumn headerText="Type" dataField="Type"/>
		<mx:DataGridColumn headerText="Marque" dataField="Marque"/>
		<mx:DataGridColumn headerText="Couleur" dataField="Couleur"/>
		<mx:DataGridColumn headerText="Prix" dataField="prix" itemRenderer="renderer.MonRenderer"/>
	</mx:columns>
</mx:DataGrid>

A présent les cellules dont le prix est inférieur à 10000 se colorisent correctement. Pour coloriser la ligne complète c'est très simple : appliquons l'ItemRenderer sur toutes les colonnes du DataGrid :

<mx:DataGrid height="200" width="350" dataProvider="{mesDonnees_AC}">
	<mx:columns>
		<mx:DataGridColumn headerText="Type" dataField="Type" itemRenderer="renderer.MonRenderer"/>
		<mx:DataGridColumn headerText="Marque" dataField="Marque" itemRenderer="renderer.MonRenderer"/>
		<mx:DataGridColumn headerText="Couleur" dataField="Couleur" itemRenderer="renderer.MonRenderer"/>
		<mx:DataGridColumn headerText="Prix" dataField="prix" itemRenderer="renderer.MonRenderer"/>
	</mx:columns>
</mx:DataGrid>

L'effet présent lors du survol ou la sélection d'une ligne utilisant notre itemRenderer n'est pas parfait. Corrigeons cela en ajoutant dans notre la classe cette vérification :

var grid1:DataGrid = DataGrid(DataGridListData(listData).owner);
if (grid1.isItemSelected(data) || grid1.isItemHighlighted(data))
return;
if (uint(data.prix<10000))
{
	g.beginFill(0x99cc99);
	g.drawRect(0, 0, unscaledWidth, unscaledHeight);
	g.endFill();
}

Le rendu final :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Modifier le formatage du texte

Nous allons voir ici comment modifier la couleur du texte présent dans notre DataGrid toujours en manipulant notre ItemRenderer. Dans notre classe MonRenderer ajoutons cette fonction :

override public function set data(value:Object):void
{
	//pour le texte
	if(value != null)
		{
		super.data = value;
		if(uint(value.prix)>30000) 
		{
			setStyle("color", 0xFF0000);
		}
		else 
		{
			setStyle("color", 0x000000);
		}
	}
}
Nous pouvons évidement modifier plus que la couleur du texte :
  • setStyle(“fontSize”, 15); pour modifier la taille du texte.
  • setStyle('fontFamily', 'georgia'); pour modifier la font.

Ajouter un composant CheckBox

L'objectif ici sera d'afficher dans la première colone du Datagrid une case à cocher. Nous allons pour cela utiliser la propriété ItemRenderer du composant Datagrid.

Ajoutons d'abord cette colonne dans notre DataGrid :

	<mx:DataGrid height="200" width="350" dataProvider="{mesDonnees_AC}">
		<mx:columns>
			<mx:DataGridColumn
				headerText="" dataField="activation" width="50"
				rendererIsEditor="true" editorDataField="result"
				itemRenderer="renderer.checkRenderer"/>
			<mx:DataGridColumn headerText="Type" dataField="Type"/>
			<mx:DataGridColumn headerText="Marque" dataField="Marque"/>
			<mx:DataGridColumn headerText="Couleur" dataField="Couleur"/>
 
		</mx:columns>
	</mx:DataGrid>

Pour cela nous allons créer un nouveau composant. Ici il sera créé dans l'arborescence src\renderer\. Ce composants MXML sera basé sur une VBox et contiendra uniquement le code ci-dessous :

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="center">
	<mx:Script>
		<![CDATA[
			// propriété pour la nouvelle valeur
			public var result:Boolean=false;
 
		]]>
	</mx:Script>
	<mx:CheckBox id="cb_rendu" selected="{data.activation}" updateComplete="result=cb_rendu.selected"/>
</mx:VBox>

Vérifions à présent que notre DataGrid utilise bien notre composant CheckRenderer:

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

La case se coche automatiquement car dans notre collection l'item “activation” retourne un booleen (true = coché, false = décoché).

Essayer par exemple avec la source de données suivante :

[Bindable] private var mesDonnees_AC:ArrayCollection = new ArrayCollection([
		{Type:"Voiture", Marque:"Renault", 
			Couleur:"Rouge", activation:"oui", prix:80000}, 
		{Type:"Voiture", Marque:"Renault", 
			Couleur:"Vert", activation:"non", prix:35000},  
		{Type:"Voiture", Marque:"Peugeot", 
			Couleur:"Jaune", activation:"non", prix:22300},  
		{Type:"Voiture", Marque:"Citroen", 
			Couleur:"Orange", activation:"non", prix:20000},  
		{Type:"Moto", Marque:"Honda", 
			Couleur:"Rouge", activation:"non", prix:20000}, 
		{Type:"Moto", Marque:"Honda", 
			Couleur:"Rouge", activation:"non", prix:30000},  
		{Type:"Moto", Marque:"Yamaha", 
			Couleur:"Rouge", activation:"non", prix:3000},  
		{Type:"Moto", Marque:"Yamaha", 
			Couleur:"Rouge", activation:"non", prix:1200} ]);

Si votre donnée n'est pas formatée correctement (comme dans l'exemple ci-dessus) un traitement devra y être appliqué. Celui-ci, par exemple, après le chargement de la donnée :

private function init():void{
	for each(var item:Object in mesDonnees_AC)
	{
		item.activation=="oui" ? item.activation=true : item.activation=false;
	}
	mesDonnees_AC.refresh();
}

Traitement des modifications du DataGrid

Nous souhaitons à présent pour les besoin de notre application récupérer les modifications effectuées sur ces cases à cocher.

Modifions le DataGrid de cette façon :

<mx:DataGrid width="200" height="350" id="dg_tacheLiaison" dataProvider="{mesDonnees_AC}" 
		editable="true" itemEditEnd="itemEditEndHandler(event)">
		<mx:columns>
			<mx:DataGridColumn
				headerText="" dataField="activation" width="50"
				rendererIsEditor="true" editorDataField="result"
				itemRenderer="renderer.checkRenderer"/>
			<mx:DataGridColumn headerText="Type" dataField="Type" editable="false"/>
			<mx:DataGridColumn headerText="Marque" dataField="Marque" editable="false"/>
			<mx:DataGridColumn headerText="Couleur" dataField="Couleur" editable="false"/>
 
		</mx:columns>
</mx:DataGrid>

Dans la déclaration du datagrid nous spécifions le paramètre Editable à True et nous lui demandons d'écouter l'évenement ItemEditEnd.

Voyons à présent la fonction déclenchée lors de l'ItemEditEnd :

private function itemEditEndHandler(event:DataGridEvent):void
{
   // reference au datagrid
   var grid:DataGrid = event.target as DataGrid;
 
   // cellule en cours d'édition
   var field:String = event.dataField;
 
   // ligne en cours d'édition 
   var row:Number = Number(event.rowIndex);
 
   // colonne en cours d'édition
   var col:int = event.columnIndex;
 
   if (grid != null)
   {
 
      // valeur avant modification
      var oldValue:Boolean = Boolean(grid.dataProvider.getItemAt(row)[field]);
 
 
      // nouvelle valeur
      var newValue:Boolean = Boolean(grid.itemEditorInstance[grid.columns[col].editorDataField]);
 
 
 
      // test si valeur modifiée
      if (newValue != oldValue)
      {
      	// a faire si la valeur change
        trace("newValue : " + newValue + " oldValue : " + oldValue);
 
	// pour récuperer une autre valeur de la ligne en cours d'édition	   
	trace(String(grid.dataProvider.getItemAt(row)['couleur']));
      }
 
   }
}

Nous pouvons ainsi détecter les changements effectués et réagir en fonction (ici un simple trace).

Si vous vous posez la question de comment intervenir sur l'édition, par exemple contrôler que les changements demandés par l'utilisateur conviennent, vous pouvez lire cette page de la documentation.


En savoir plus

Nous n'avons vu ici qu'une petite partie de ce qu'il est possible de faire. Pour aller plus loin, vous pouvez lire: