jueves, 5 de febrero de 2009

Datagrid con un ItemRenderer Propio (Personalizado)


En esta oportunidad vamos a colocar un ItemRenderer personalizado dentro de un DataGrid y que sin embargo los datos se sigan pasando de manera automatica a través del dataSource y utilizando Binding.

El ItemRenderer que vamos a utilizar va a ser un componente flex creado completamente aparte y a nuestro gusto, y le vamos a pasar sus datos a renderizar a través de la propiedad Data que tienen todos los objetos que implementan la interfaz IDataRender.

Para empezar vamos a entender un poco sobre la interfaz IDataRenderer, cualquier objeto que la implemente contiene una propiedad llamada data, por donde recibe toda la información a renderizar (a pintar, graficar, como lo quieran llamar), la única informacion que un objeto de este tipo deberia recibir a través de otras propiedades seria la concerniente a su comportamiento.

En nuestro ejemplo la informacion a renderizar son dos datos:

  • url: Contiene la direccion donde se encuentra alojada la fotografia del producto.
  • nombre: El nombre del objeto.
El ItemRenderer por defecto en el DataGrid es el componente "Label", aunque a veces no nos damos cuenta. Si queremos cambiar el itemrenderer de una columna solo debemos setearle la propiedad "itemrenderer" igual a la dirección donde se encuentra nuestra clase (o componente), esta dirección debe incluir la ruta desde la raiz del proyecto. Una vez hecho esto el itemrenderer recibirá la información a través de la propiedad "data" de la que hablamos anteriormente.

Bueno basta de hablar tanto y vamos a empezar. Creamos el componente de flex que va a renderizar los datos:
Archivo pictureRender.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="112" height="126">
<mx:Script>
<![CDATA[

[Bindable]
public var nombre : String = "Ramon";
[Bindable]
public var url : String = "assets/1.jpg";

public override function set data(value:Object):void
{
nombre = value.data.nombre;
url = value.data.url;

super.data = value;
}
public override function get data():Object
{
return super.data;
}
]]>
</mx:Script>
<mx:Image x="10" y="10" width="89" height="89" source="{url}"/>
<mx:Label x="10" y="104" width="92" text="{nombre}"/>
</mx:Canvas>

El componente lo hemos creado a partir de la clase Canvas, como esta clase implementa la interfaz IDataRenderer, sobreescribi los metodos get y set de la propiedad data para aplicarle una logica especial a estos datos, ya que debemos extraer el campo "nombre" y "url" de este objeto para colocarlo en las respectivas variables del componente, estas variables deben ser declaradas como [Binding] en el momento de su definición, ya que de esta manera los datos que ellas contengan serán transferidos al objeto Image (en el caso de la url) y Label (en el caso del nombre) sin nosotros tener que ocuparnos de eso, es decir, en el momento en que cambie la variable url entonces cambiara el valor de la propiedad "source" del objeto Image. Para aprender un poco mas sobre el metatag [Binding] puede hacer click aqui.

Ahora procedemos a llenar el archivo de la aplicacion:
Archivo DatagridDataRender.mxml


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.core.IDataRenderer;
import mx.collections.ArrayCollection;

[Bindable]
public var renderData : ArrayCollection = new ArrayCollection( [
{url:'assets/1.png', nombre:'Monitor Daslex'},
{url:'assets/2.png', nombre:'Maletin Ladrix'}]);
[Bindable]
public var datosDG : ArrayCollection = new ArrayCollection();
public function init() : void
{
var obj1 : Object = new Object();
obj1.data = renderData.getItemAt(0);
obj1.descripcion = "Producto de buena calidad.";
var obj2 : Object = new Object();
obj2.data = renderData.getItemAt(1);
obj2.descripcion = "Producto de mala calidad.";

datosDG.addItem(obj1);
datosDG.addItem(obj2);
}
]]>
</mx:Script>
<mx:DataGrid x="10" y="10" dataProvider="{datosDG}" rowHeight="130" width="373" rowCount="2">
<mx:columns>
<mx:DataGridColumn headerText="Producto" dataField="data" itemRenderer="pictureRender" />
<mx:DataGridColumn headerText="Descripcion" dataField="descripcion"/>
</mx:columns>
</mx:DataGrid>

</mx:Application>
Este archivo tiene dos partes fundamentales, en la primera seccion definimos dos ArrayCollection llamados "renderData" y "datosDG". El primero de ellos contiene los objetos "data" que se van a utilizar para enviar informacion a los ItemRenderer, el segundo de ellos va a ser sincronizado con la propiedad dataProvider del DataGrid (contendrá una lista donde cada item será equivalente a una fila en el datagrid.)

La función init, que se llama cuando se dispara el evento creationComplete de la aplicación, se encarga de llenar el ArrayCollection datosDG, especificamente crea objetos con dos variables principales "data" y "descripcion", estas variables deben ser colocadas como "dataFields" en las columnas del DataGrid para que el DataGrid haga la carga de datos automaticamente. Si se fijan, la pripiedad data es llenada con la información a renderizar por el ItemRederer.

Bueno ya hemos finalizado nuestra aplicación, cualquier duda me pueden escribir a mi correo aalejo@gmail.com, si todo los hicieron correctamente su aplicacion debería verse de la siguiente manera:


8 comentarios:

  1. Mi problema es que tengo mis datos en un ArrayCollection y cuando hago scroll el item render se refresca incorrectamente, tengo celdas que cambian a rojo cuando hay un valor negativo, y a verde cuando es positivo, esta funcionalidad no funciona bien cuando hago scroll al data grid.

    ResponderEliminar
  2. Yerry tu problema es muy frecuente en este tipo de situaciones, lo que sucede es que debes asegurarte de que el objeto "data" de cada una de estas celdas esta correctamente seteado, este problema ocurre porque aparentemente no haz llenado realmente los objetos data de cada itemrenderer. Fijate con el debugger a ver que informacion contienen.

    ResponderEliminar
  3. hola amigo como estas tengo un problemita estoy listando un archivo xml en un datagrid en flash y todo ok hasta ahi el llenado q hago es full codigo

    ahora lo q kiero hacer es meterle un link o url en cada celda pero llenado desde mi xml como si fuera un atributo mas de mi xml gracias si puedes me respondes al aqueque21@gmail.combye men

    ResponderEliminar
  4. hola, apenas llevo algunos dias metiendome en esto de flex, y he llegado a un punto donde no encuentro como¡¡¡ estoy haciendo un simple ejemplo en el cual tengo una datagrid de 3 columnas y las quiero llenar de forma dinamica a traves de tres input text, los cuales deseo controlar desde un boton "agregar", es decir, que al llenar (via teclado) los campos, se pueda hacer clic en el boton y los datos que estas cajas de texto posean sean guardados en la data grid. No se como hacerlo, antes he manejado (poco) java y ahora el manejo del codigo me hace muchos enredos, gracias de antemano por tu ayuda.

    ResponderEliminar
  5. y una disculpa si mi pregunta es muy obvia, pero he estado checando varios codigos, que como manejan cosas mas complejas supongo, no les entiendo del todo, para empezar xq manejan de distintas formas a las variables (variables: datos como nombre, apellido,etc. que pretendo sean ingresados desde las cajas de texto) y luego xq en el metodo o evento que ocurro en el boton igual lo manejan diferente. ojala y te des un tiempecito para ayudarme.

    ResponderEliminar
  6. tengo un problema con un dataGrid. tengo una lista de objetos de tipo Siniestro. Dentro estos objetos tienen como atributo un Objeto de tipo Direccion y a la hora de mostrarlo con el dataGridColumn no hay manera....

    en el dataProvider del dataGrid establezco la lista "listaSiniestros". Todos los atributos del objeto Siniestro que son atributos no complejos me los muestra bien pero cuando me pongo a mostrar un objeto complejo no hay manera...

    Me podeis ayudar????

    ResponderEliminar
  7. un pregunta como guardo un itemrender, en una base de datos!????

    ResponderEliminar
  8. disculpa como puedo crear un boton para eliminar una fila del data grid con itemrenderer, estoy haciendo una aplicacion para escritorio y ps me sale error cuando le doy ala propiedad itemrenderer y el archivo q cree, talvez algun dato mas q deba saber, ayuda porfavor

    ResponderEliminar