lunes, 15 de marzo de 2010

[ASP.NET] – Pasar valores entre dos GridView

 

Introducción


El objetivo de este articulo es demostrar como pasar valores entre dos controles GridView.

El pasaje de las filas entre ambos controles será soportada gracias al uso de objetos Session de asp.net, y al uso de DataSet para conservar el conjunto de registros.

Para darle algo mas de estabilidad a lo desarrollado se opto por la utilización de dataset tipados.

 

imagen

 

Definición de las grillas


Ambas grillas son idénticas en cuanto es definición, poseen los mismo campos, y controles de selección, en este caso se opto además por usar el mismo estilo.

La deferencia radica en el nombre de cada grilla, y en el mensaje cuando estas no contienen registros.

 <asp:GridView ID="gvArticulos" runat="server" AutoGenerateColumns="False" 
        CellPadding="4" ForeColor="#333333" GridLines="None" DataKeyNames="Id">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:TemplateField>
        
            <ItemTemplate>
                <asp:CheckBox ID="chkSeleccion" runat="server" />
            </ItemTemplate>
        
        </asp:TemplateField>
        <asp:BoundField DataField="Descripcion" HeaderText="Descripcion" />
        <asp:BoundField DataField="Precio" HeaderText="Precio" />
    </Columns>
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
     <EmptyDataTemplate>
         No hay registros
     </EmptyDataTemplate>
    <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <EditRowStyle BackColor="#2461BF" />
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>

Es importante notar la definición del checkbox, para marcar cada ítem que se seleccionara para pasar a la otra lista.

 

Cargar Grids


El evento Pag_Load, realizara la inicialización de los datos de ambas grillas.

La que listara los artículos necesitara de un método que devuelve la información, por un tema de practicidad se están armando en runtime, pero nada impide que provengan de una base de datos, o algún otro origen.

La lista de selección, será inicializada sin registros, simplemente para que muestre la leyenda que se ha configurado cuando esta no posee datos.

Por ultimo la información visualizada también es asignada a los correspondientes objetos de Session para conservar la información y poder trabajarla entre request de la pagina.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        gvArticulos.DataSource = ObtenerLista();
        gvArticulos.DataBind();

        //
        // Esta linea es suada para inicializar la grilla de seleccion
        // y que esta muestrre el mensaje informando que no hay items
        // seleccionados
        //
        gvSeleccion.DataSource = new dtArticulos.ArticulosDataTable();
        gvSeleccion.DataBind();

        Session["articulos"] = ObtenerLista(); ;
        Session["seleccion"] = new dtArticulos.ArticulosDataTable();
    }
}

Selecciona Items


La selección y pasaje del ítem marcado a la otra grilla requiere de varios pasos:

- Se recuperan los datos de cada grilla, que han sido guardados en los objetos de Session

- se recorre cada fila de la grilla de origen, recuperando y verificando si el checkbox de esa fila ha sido marcado

- si el registro fue seleccionado, se arma con la información del gridview un nuevo row, agregando el resultado al previamente recuperado datatable desde la Session

- se busca por el Id el registro en el conjunto de datos original, y se procede a quitarlo del conjunto de datos

- por ultimo se bindean las grillas con los dataset resultantes para que permitan visualizar el resultado y se guarda en la Session

 

protected void btnSeleccionar_Click(object sender, EventArgs e)
{
    dtArticulos.ArticulosDataTable dtArt = Session["articulos"] as dtArticulos.ArticulosDataTable;
    dtArticulos.ArticulosDataTable dtSel = Session["seleccion"] as dtArticulos.ArticulosDataTable;
    
    foreach (GridViewRow row in gvArticulos.Rows)
    {
        CheckBox check = row.FindControl("chkSeleccion") as CheckBox;
        
        if(check.Checked)
        {
            //
            // Se arma la fila para el DataSet de seleccion
            //
            dtArticulos.ArticulosRow articulo = dtSel.NewArticulosRow();
            articulo.Id = Convert.ToInt32(gvArticulos.DataKeys[row.RowIndex].Value);
            articulo.Descripcion = row.Cells[1].Text;
            articulo.Precio = Convert.ToInt32(row.Cells[2].Text);

            dtSel.Rows.Add(articulo);

            //
            // Se busca el registro en el DataTabla por el Id
            // este metodo devolvera una coleccion de filas, pero es sabido 
            // de antemano que solo sera encontrado una row para el filtro utilizado
            //
            DataRow[] rowdelete = dtArt.Select(string.Format("Id={0}", articulo.Id));
            dtArt.Rows.Remove(rowdelete[0]);

        }
    }

    gvArticulos.DataSource = dtArt;
    gvArticulos.DataBind();

    gvSeleccion.DataSource = dtSel;
    gvSeleccion.DataBind();

    Session["seleccion"] = dtSel;
    Session["articulos"] = dtArt;

}

 

[C#]
[VB.NET]

35 comentarios:

  1. Hola Leandro. He llegado a tu blog porque precisamente ando desarrollando un control de usuario que me permite pasar elementos de un DataGridView a otro. El control funciona bien. Pero tengo un problema y es que ambos DataGridView están 'bindeados' a un respectivo DataTable, y estos DataTable los obtengo luego de ejecutar dos procedimientos almacenados respectivamente. El primer DataTable, el que si bindeará al DataGridView de la derecha, contiene todos los valores disponibles a ser seleccionados, excepto lo que ya fueron seleccionados anteriormente. En el segundo DataTable, el que se bindeará al DataGridView de la izquierda, contiene todos los valores que han sido seleccionados. Me gustaría usar la propiedad RowState para determinar en el segundo DataTable (el de los datos seleccionados), que filas han sido removidas, es decir, pasadas al otro lado (izquierda), y que filas han sido agregadas, es decir pasadas del DataGridView de la izquierda. Pero no sé por qué razón, a la hora de revisar el RowState del DataTable de la derecha, sólo me aparecen las filas agregadas, y se pierde la referencia de las filas eliminadas (es decir pasadas a la izquierda). El tema es que ahora, al no poder basarme en el RowState, para determinar cuáles filas fueron agregadas o eliminadas, me tocaría realizar un método que determine ésto. ENtonces me gustaría, si te es posible que me ayudaras a solucionar ésto que te planteo. Muchas gracias por tu atención.

    ResponderEliminar
  2. Hola Leandro.
    Tengo una duda,viendo el código de la aplicación he encontrado algo que me resulta nuevo:
    dtArt.[Select](String.Format("Id={0}", articulo.Id))

    El uso de [Select] y me gustaría saber que concepto se esta aplicando, cuando y conque tipo de objetos la podría usar?? también note que existen otras clausulas que me suenan a SQL como Where y From, hay un nombre común que englobe a todas estas clausulas??

    Saludos y gracias de antemano

    ResponderEliminar
  3. hola Axel

    Ese Select() que notas alli es un metodo del propio DataTable, que no te confunda con el Select de linq, en este caso no lo es

    DataTable.Select (Método)

    Las del Where y From esas si podrian ser de linq, pero no recuerdo haberlas suado ene ste articulo.

    saludos

    ResponderEliminar
  4. hola buenas noches leandro.

    tengo una duda al pasar datos de un gridview a un popup. mas que nada necesito pasar un valor de la fila donde tengo mi hyperlink para poder utilizarlo en el popup y poder actualizar los datos de la fila donde selecciono el hyperlink

    espero me puedas orientar porke no se mucho de asp.net

    saludos buen dia

    ResponderEliminar
  5. hola Estudiante de programacion

    de que clase de popup se trata?, usas javascript con window.open() o es el modalpopup de ajax toolkit

    saludos

    ResponderEliminar
  6. Eres mi nuevo ídolo, tenia días intentando hacer esto ya casi estaba cerca pero no daba con la clave. Te felicito por tus colaboraciones y espero poder ser tan buena como para atreverme a compartir mis ideas :D

    ResponderEliminar
  7. Hola que tal Leandro,

    Tengo un problemilla, estoy ejecutando el programa que nos hiciste favor de pasar, que esta excelente, pero tengo un problemilla, cuando lo ordeno por cualquiera de las columnas se pierden los colores.

    sabrás la forma para que no pase esto.

    Saludos...

    ResponderEliminar
  8. hola Wences Cervantes

    no estoy seguro de recordar como es que se habia implementado el tema de aplicar estilo o colores al grid

    pero imagino que despues de ordenar los datoas deberia volver aplciarse la logica que define el color en el datagridview, para que los estilos aparezcan nuevamente

    mas si esta operacion recarga los datos del grid

    saludos

    ResponderEliminar
  9. Hola Leandro! muy interesante el ejemplo. Pero en mi caso me piden lo mismo pero con conexion a base de datos, mejor dicho los valores que se muestran en el gridview son de una tabla de la BD. ¿Como seria? Estoy programando con capas en vb.net . esa es mi duda, espero puedas ayudarme. ¡¡Gracias!!

    ResponderEliminar
  10. hola Jose

    es lo mismo, solo en el momento de obtener la lista que asignas al grid realzias una query a la db

    o en tu caso instanciaras la capa de datos para recupoerarla

    la operacion de pasaje es algo de la presentacion como tomes los datos de la db no cambia

    saludos

    ResponderEliminar
  11. Hola que tal Leandro, muchas gracias por tu trabajo, aunque tengo problemas para implementarlo en mi proyecto ya que yo necesito que solo tenga 1 campo seleccionado, espero me puedas auxiliar, ya intente con el group name pero no me da lo que necesito saludos!

    ResponderEliminar
  12. hola jackzerox

    no entendi, como que un campo seleccionado, si lo que seleccionas son checks, o apuntas a que solo un check podria estar marcado para pasar el registro

    si es asi podrias validarlo, o sea deja que se marque ams de uno pero antes de realizar la oepracion en la accion del boton validas si hay mas de una seleccion, si la hay lo informas y no continuas el proceso

    saludos

    ResponderEliminar
  13. Muchas Gracias Leandro, lo resolvi con el evento OnCheckedChanged, ya que no use boton para pasar la informacion, pero ahora necesito saber si se puede llenar 2 grid view, desde la BD pero que los registros que aparecen en un Grid View no aparescan en el otro Digamos que tengo dos tablas
    Table 1 Table 2
    1 2
    2 4
    3 5
    4
    5
    Cuando Llene un grid view1 con la Tabla1 no aparescan los datos que tengo en grid view2 que se lleno con la tabla2. Saludos y Muchas gracias me gusta tu blog!

    ResponderEliminar
  14. hola jackzerox

    podrias suar un JOIN entre las tablas para determinar que registrso estan en una tabla y no en otra

    SELECT T.campo
    FROM Tabla1 T1 LEFT JOIN Tabla2 T2
    ON T1.campo = T2.campo
    WHERE T2.campo IS NOT NULL

    con eso muestras los registros de T1 que no estan en T2

    saludos

    ResponderEliminar
  15. Nuevamente Leandro muchas gracias por tu ayuda, ya pude avanzar por completo en mi proyecto, solo hacia el Join pero no con el null saludos y muchas gracias de nuevo!

    ResponderEliminar
  16. Hola Leandro.
    ¿Se puede realizar el paso de datos entre grillas, pero con listas genéricas?
    Estoy usando un DAO para acceder a los datos de la base y me manejo con listas genéricas para traer los mismos transformados a objetos del negocio.
    Muchas gracias.
    Saludos

    ResponderEliminar
  17. hola Gabriel

    claro que se puede, lo que implemente es un ejemplo, pero la tecnica aplcia de igual forma con cualqueir otro tipo de coleccion

    por supuesto se deberias cambiar la forma en que se trabaja esa coleccion

    ya que la forma de castear al tipo de datos, o de agregar items nuevos eso va a diferir

    saludos

    saludos

    ResponderEliminar
  18. Hola Leandro
    Tengo un problema al cargar los datos de la base de datos y posteriormente a un DataTable para cargarlos a un GridView. INtente modificar el codigo que pusiste de ejemplo pero no me carga nada, este es el codigo que utilizo para intentar cargar los datos;

    dtArticulos pro = Productos.Producto();
    gvArticulos.DataSource = pro;
    gvSeleccion.DataMember = "Articulos";
    gvArticulos.DataBind();

    //
    // Esta linea es usada para inicializar la grilla de seleccion
    // y que esta muestrre el mensaje informando que no hay items
    // seleccionados
    //
    gvSeleccion.DataSource = new dtArticulos.ArticulosDataTable(); // Aqui no se si se queda igual
    gvSeleccion.DataBind();

    Session["articulos"] = pro ;
    Session["seleccion"] = new dtArticulos.ArticulosDataTable(); // Aqui no se si se queda igual

    Ojalame ayudes

    ResponderEliminar
  19. hola radx

    la verdad ese fragmento de codigo no lo entiendo, parece que asignas instancias nuevas al gridview, pero no logro entender en que accion realizas esto

    creo que seria mejor si quieres seguir el tema hacerlo en el foro

    asp.net foro

    alli podras poner mejor el codigo, para analizarlo, por este medio el codigo no queda bien identado para su intepretacion

    saludos

    ResponderEliminar
  20. Hola Leandro, te molesto con algo, en un gridview de consulta tengo unos checkbox, unos esta chekeaado otros no, segun la informacion q se ingreso en el formulario...
    este gridview lo tengo diseñado para que las filas se puedan selecionar y cargar la informacion en otro formulario para la edicion de la informacion, pero no se como pasar los chekbox del gridview a los chekbox correspondientes del formulario de destino...
    me puedes colaborar muchas gracias

    ResponderEliminar
  21. hola Hernán

    podrias como hago aqui

    [GridView] Mantener checkbox durante la paginación

    usar linq para tomar los ids de las rows marcadas para cargar una lista con estos valores y poniendolos en un objeto Session pasarlos a la otra pagina

    saludos

    ResponderEliminar
  22. hola leandro
    Estoy realizando mi proyecto y necesito que al seleccionar un campo del gridview, me habra otro formulario y en el poder agregar los detalles de el campo anteriormente seleccionado y al terminar de agregar los detalles poder guardarlos en la base de datos, pero que solo sean los detalles del campo seleccionado en el anterior formulario.

    ResponderEliminar
  23. Hola leandro,gracias por el aporte que haces a la comunidad de programadores.Queria preguntarte si no tenes un ejemplo que haga lo mismo que este ejemplo pero con la diferencia que las grillas esten en distintos formularios,ya que busque en la web y no encuentro algo similar.Habia un ejemplo de pepluis creo que se llama,pero tambien era en el mismo form las 2 grillas.Y mucho mejor si es vb.Saludos desde argentina.

    ResponderEliminar
  24. hola Andres

    el tema es que al haber navegacion entre dos forms vas a necesitar algo que conserve los datos entree las pantallas

    quizas podrias usar el objeto Session para mantener alli una lista o coleccion en memoria entonces cuando seleccionas en un webform agregas a la coleccion de la session ese item seleccionado y al ir a la otra pagina muestras lo que conservas en session

    en este caso la session conserva la coleccion intermedia de items seleccionados

    saludos

    ResponderEliminar
  25. Hola Leandro

    dejame decirte que esta muy interesante como planteaste el cambio entre valores en los grids, me gustaria ver el proyecto pero desgraciadamente los archivos no estan disponibles espero que puedas volver a cargarlos, tienes un blog excelente, he aprendido bastantes cosas aqui sigue asi felicidades.

    Saludos

    ResponderEliminar
  26. hola Lauro

    el codigo ya esta actualizado

    saludos

    ResponderEliminar
    Respuestas
    1. Hola Leandro, me parece interesante,¿donde podemos descargar la solución?

      Eliminar
  27. Q tal leandro, esto lo quisiera hacer con datos desde un base de datos, no se si me puedas ayudar, de antemano gracias.

    ResponderEliminar
  28. hola Hermes

    no entendi, que es lo que quieres hacer con datos desde un base de datos?

    saludos

    ResponderEliminar
  29. Saludos, Leandro como se haría en el caso que sea una ButtonField en el gridview #1 y al pasar los datos del gridview se pasen los registros y me cree unos tres campos mas al gridview #2, estoy confundido con el manejo de manejar dos gridview, si me puedes ayudar le agradeceria mucho.

    ResponderEliminar
  30. Hola. Buenos días.
    Necesito saber si de alguna manera me podría ayudar a mí, yo tengo una tabla de materiales, almacena cada material que tiene un modelo (hablo de ropa), necesito hacer que todo el material de un modelo lo pueda copiar a la misma tabla pero cambiando la talla del modelo, ya que son varios modelos iguales y lo único que cambia es la talla, ocupa el mismo material pero no sé como hacer para que cuando busque el modelo y mande los datos al gridview pueda copiar desde un botón, y sólo poder poner el nuevo modelo al que le registraré el material. Estoy trabajando en Visual Studio 2012 asp.net c# con Sql Server Management Studio.
    Espero darme a entender y me pueda ayudar.
    Buen día.

    ResponderEliminar
  31. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  32. Hola, disculpa tengo una duda, es que ando buscando como poder conservar los datos de mi gridview si me meto a otra pagina... Te lo resumo:
    Tengo una página llamada "Productos Cereales" en donde me meto a la categoría de Cereales, entonces le doy click a uno y en otra página (Agregar al carrito) así se llama mi otra página, ahí mando los datos de mi producto agregado en mi página "Producto Cereales" entonces al entrar a mi página "Carrito de compras" ahí se conservan los productos a los que les di click... AHORA si me me regreso o me meto a otra página como por ejemplo "Producto Aceites" o alguna otra.. Cuándo regreso a mi Carrito de compra YA NO estan las que tenia... ¿Alguien podría orientarme? De antemano Gracias.

    ResponderEliminar