lunes, 2 de abril de 2012

ASP.NET–GridView anidados (maestro-detalle) (GridView nested)

 

Introducción

El objetivo en el articulo será el demostrar como armar un grid con jerarquía, en este caso mostrando las ordenes de compra de un cliente

Además se pretende demostrar como se puede armar una entidad compleja que retorne los datos en una estructura anidada de listas

 

Detectar despliegue detalle

Uno de los puntos mas importantes en la implementación esta relacionado con la forma en que se detecta el expandir\colapsar del detalle

En la imagen se remarcan dos atributos creados con este propósito, la idea es poder relacionar la imagen con el tag <tr> que permite ocultar o mostrar el grid del detalle

La idea detrás de esto es ayudar luego a jquery para poder determinar que elementos intervienen en la acción

con jquery se extrae el id de la orden, para luego usarlo de selector del <tr> que posee ese mismo id

el toggle() solo permite switchear entre visible\invisible, y detectando el estado mostrar una imagen u otra

 

Estructura de datos jerárquica

La estructura usada para el modelo relaciona tres clases

La idea es mostrar como al cargar los datos, es analizar como los métodos se invocan unos a otros para recuperar la info enlazada en al jerarquía

 

Código

El codigo fue confeccionado con Visual Studio 2008 y base de datos Sql Compact 3.5

[C#]
[C# SkyDrive]

110 comentarios:

  1. Buenas!
    Antes de nada, darte las gracias por todas las dudas que tu blog me ha solucionado.

    A ver si me doy explicado con claridad para saber si me puedes solucionar el problema que tengo.

    Necesito tener un gridview en el que:
    -En la Columna(0) se muestren los valores de una consulta sql (en este caso serían los colores disponibles en almacén de un articulo)
    -En la fila(0) se muestren los valores de otra consulta sql (en este caso las tallas disponibles en almacén de un articulo)

    ResponderEliminar
  2. hola Adri

    y no podrias lograr eso usando el evento RowDataBound ?

    o sea asignas al datasource del grid el resultado de la query de las filas

    y en el RowDataBound tomarias la primer columna, ejecutarias la otra query y asignarias los colores a esa columna seleccionada para esa fila que se crea

    saludos

    ResponderEliminar
  3. Al final no puedo hacer nada de eso porque el tipo de datos me lo imposibilita mediante una consulta... :S

    Ahora me surgió otra duda... Hay alguna manera de copiar un dataset en un Array? como sería? nunca trabajé con vectores y no me doy acostumbrado a ellos..

    Gracias!

    ResponderEliminar
  4. hola Adri

    un dataset a un array ?
    la verdad no lo recomendaria

    podrias si definir uan clase con sus propiedades y generar una lista genrica de esta clase

    entonces recorrer las filas del datatable y volcar cada campo a las propiedades

    saludos

    ResponderEliminar
  5. Hola, una pregunta, el ejemplo sirve para un anidamiento recursivo, estoy buscando la manera de armar una aplicacion para el registro de actividades que a su vez puede tener subactividades (que es una misma entidad "Actividad") y a su vez esta otra subactividad...etc. No encuentro la manera de solucionar esto. Raro que haya mas de 3 anidadas, pero se podria dar el caso. Tenes alguna idea de como podria mostrar esto? La estructura ya la tengo armada, la entidad actividad tiene un IDPadre, con esto se si es una subactividad, si es cero es una actividad raiz. Cualquier ayuda se agradece, estoy con esto a modo personal hace meses y no le encuentro la vuelta con el Gridview ni con controles de terceros, mas que nada para mostrarlo en modo de jerarquia por Actividad, o sea Actividad -> subactividad (si existe) -> subatividad de subactividad, etc...Espero haberme explicado Saludos.

    ResponderEliminar
  6. hola julio

    podria funcionar si sabes que los niveles son fijo, o sea si dices los niveles son siempre 3 o 4 y defines el html del gridview para soportar esta situacion

    pero hacerlo dinamico que algunas entidades tengan 2 niveles, otras 4 y asi las variantes los veo complicado

    se podria definir en el html del grid los niveles maximos que se puede alcanzar y de ultima si solo se llega al segundo nivel dejar los grid contenido sin asignar el DataSource, como son gridview sino asignas info no se muestra el grid

    pero la verdad esto no lo he probado

    saludos

    ResponderEliminar
  7. tengo una pregunta y es la siguiente: ya hice unas modificaciones segun lo q requiero y al visualizar el proyecto, me sale esto: "breaking on JScript runtime error -'$' is undefined" y hace referencia a esta secuencia:

    $(function().

    que debo hacer?
    gracias.

    ResponderEliminar
  8. ya solucioné el error y era q tenia un ( de más.
    Pero ahora me sale esto: validation (XHTML 1.0 Transitional): Attribute 'orderid' is not valid attribute of element 'img' y no me muestra la tabla.

    ResponderEliminar
  9. muchas gracias Leandro, su explicación me ha servido para solucionar un marronceteme guardo su blog para el futuro

    ResponderEliminar
  10. Hola Leandro!!
    Disculpa por preguntarte en este espacio pero no haye donde mas hacerlo, mi pregunta es un poco afuera de este tema pero algo relacionado: ¿es posible correr una aplicación asp.net en windows server 2008 (ISS 7) hecha en un windows XP + VS 2000 (framework 1.0 creo q es)? En caso que sea negativo, me imagino que no se puede migrar la aplicación a VS 2010?

    ResponderEliminar
  11. Muchas gracias Leandro, el link me da error pero ahora sé qué tema buscar, y al parecer si se puede, gracias por aclarar mi duda

    ResponderEliminar
  12. este ultimo que pusiste si abre, intentaré instalarlo, mil gracias

    ResponderEliminar
  13. Buen dia Leandro.
    Necesito crear un grdview que cargue de una tabla sql datos, que por su valor los coloque segun la columna y fila que corresponda.
    y lo que mas me complica, es que, es posible que la celda deba contener mas de un dato a la vez (Maximo 4 datos).
    Basicamente es un tablero de alarmas.
    Me podras dar una idea de como armarlo por favor?
    Puedo pasarte el diseño modelo en excel de lo que quiero hacer para una mayor idea.
    Te dejo un abrazo y muchas gracias!!!

    ResponderEliminar
  14. hola Daniel

    lo que recomendaria es que pases la info que tomas de la db a clases que tu crees y uses esto para personalizar la info que mostraras

    recuerda que en una clase pdorias hacer

    public class Datos{

    public string dato1 {get;set;}
    public string dato2 {get;set;}
    public string result {
    get {return this.dato1 + this.dato2;}
    }

    }

    como veras con lcases puede crear columnas complejas en base a otras
    en esas podrias armar la info que necesitas para unir varias columnas en una

    por supuesto en el gridview deberias luego definir als columnas en timepo de diseño y mapear la columna compuesta nueva que creas

    saludos

    ResponderEliminar
  15. Hola Leandro, la verdad que supera todo lo que yo se ya que estoe s un hobbie para mi, soy medico en realidad, te queria preguntar una duda sobre una base en access 2003 que estoy hacieno:
    lleno un par de tablas desde un formulario, el cual tiene datos en algunas cajas de textos con datos predefinidos pero que puedo modificar, dentro de estos textbox hay 2 que son fecha y hora, cuando la informacionn esta lista para meter en la tabla presiono un botón para que esta se guarde en su respectiva tabla con 4 campos entre los que están fecha y hora, el tema es que necesito que esa fecha y hora no se repitan nunca, osea que me avise que esa hora de esa fecha ya esta ingresada en la tabla y que no ingrese los datos hasta que no ponga datos validos.
    Espero haberme explicado, la verdad no se como hacer con código o sql o ambas, muchas gracias.
    Gracias

    ResponderEliminar
  16. Tengo una duda espero me puedan ayudar estoy trabajando con Visual Studio 2005 y quiero hacer lo siguiente:
    Quiero llamar a un formulario cuando este posicionado en un textbox, les explico.

    Tengo un textbox1 un botón1 y un textbox2 el textbox1 es el que esta habilitado el botón y el tetxbox2 el focus no pasa en ellos, entonces lo que necesito es llamar a un formulario que se llama "FormProducto" el cual contiene un Datagrid dos botones uno es para salir del formulario y el otro es para Aceptar, en el cual el DataGrid tiene dos columnas una que se llama Código en donde me aparece los códigos de los productos y la otra columna que se llama descripción, entonces quiero que cuando me aparezca el formulario de los productos pueda elegir el código, y dar aceptar en el boton para pegar el codigo en el textbox1 y la descripcion en el textbox2, y que ademas yo pueda llamar al formulario presionando la tecla F4 y también que esta función solo suceda cuando este posicionado en el textbox1, porque quiero hacer esta función en el textbox3, presionando la tecla F4, creo que el botón es para realizar esa clase de función, pero aun no he podido saber como se hace.

    Ademas quisiera que sin necesidad de llamar al formulario donde están los productos solo pueda escribir el código en el textbox1 y que automáticamente me aparezca la descripción del código que corresponda en el textbox2, me quedo en espera de sus respuestas.

    ResponderEliminar
  17. hola Murray3G

    lo que podrias ahcer es validarlo

    [ADO.NET] – Parte 5 - Ejemplos Simples – Operaciones CRUD

    usar la misma tecnica que se aplcia en el articulo, si se que este usa sql server, pero casi no hay diferencia en el codigo, solo es cuestion de cambiar el Sql y poner el OleDb, por ejemplo en lugar de SqlConnection usar OleDbConnection, el resto si cambias las clases es identico

    entonces habria que centrars en el metodo Exists() si bien allis e valida un id se podria aplicar lo mismo si se pone un campo fecha o cualqueir otro, si existe devolvera registros por lo tanto devolvera true y en la validacion previo a grabar lo informas y no grabas nada

    saludos

    ResponderEliminar
  18. hola An Lel

    bueno al verdad son bastante cosas

    lo primero que podria comentarte es que analice como comunicar los formularios

    [DataGridView] Parte 3 – Pasaje de información entre grillas en distintos formulario

    con la info del link podras pasar la seelccion del grid de un form a otro

    despues lo de detectar el F4 se logra por medio del ProcessCmdKey

    Protected Overrides Function ProcessCmdKey( _
        ByRef msg As System.Windows.Forms.Message, _
        ByVal keyData As System.Windows.Forms.Keys) As Boolean
           
            If (Not TextBox3.Focused) Then _
               Return MyBase.ProcessCmdKey(msg, keyData)
          
            If (keyData <> Keys.F4) Then
                Return MyBase.ProcessCmdKey(msg, keyData)
      End If
          
    'aqui el codigo
               
            Return True
    End Function

    como veras solo si el textbox3 tiene el foco y si se presiono F4 es que se pasa y realiza la accion

    saludos

    ResponderEliminar
  19. Hola leandro, antes que nada gracias por la data muy bueno el articulo.
    Te queria preguntar, yo ya arme mas o menos todo pero cuando clikeo en la imagen no responde como si no detectara el evento. Tendria que agregar un evento onclick en el tag de la imagen?. Saludos y gracias!

    ResponderEliminar
  20. hola

    claro debes usar jquery para asignar el evento, en la imagen 3 de articulo veras que se muestra

    $('#<%=gvOrders.ClientID%> img').click(...

    eso es la seleccion de las imagenes del grid para asignar el click que permite expandir o colapsar

    valida que ese evento se este generando

    saludos

    ResponderEliminar
  21. Hola muy buena información me resolvió mi problema... Pero tengo una pregunta: el codigo javascript que colocas ($('#<%=gvOrders.ClientID %> img').click(function) funciona bien si esta dentro del mismo aspx, pero al pasarlo a un archivo .js y llamar este desde el aspx JqUERY manda este error "Syntax error, unrecognized expression: %" y no funciona el despliegue.

    ResponderEliminar
  22. hola Daniel

    es que si lo usas desde un .js debes adaptarlo
    hay varias formas quizas la mas directa seria usando

    $("[id*='gvOrders'] img")

    con el *= localizas el control por aproximacion en el nombre del id

    saludos

    ResponderEliminar
  23. mira Sr. Leandro tengo este dilema:

    Tengo un gridview1 en una de sus columnas un checkbox, si lecciono 1 o varios checkbox 1 ó 2 ó mando a cosnultar a mi bdd y lo que quiero haces es por cada checkbox seleccionado me genere gridview dentro de una fila recordando que la se pudieron seleccionar 1 o varios checkboxs. No se si estoy atacando mal el problema. Espero me orientes...

    ResponderEliminar
  24. hola MIGUELL

    que uses check o imagenes es indistinto, porque el grid y el arbol relacionado se genera al mismo tiempo con el uso del RowDataBound

    no se si los check lo usarias para colapsar o no el detalle pero no afecta a como generas el detalle

    saludos

    ResponderEliminar
  25. Excelente referencia Leandro. Me ha sido de mucha utilidad. He logrado incrustar un tercer grid; sin embargo no logro que este tercero se expanda y colapse. Creé una función Javascript 'idéntica' a la que expande el segundo grid, teniendo cuidado de cambiar el nombre correcto del grid y columna, pero no funciona. ¿Alguna sugerencia?

    ResponderEliminar
  26. hola William

    has validado si la accion de javascript se lanza ?

    podrias poner la linea

    debugger;

    en javascript para que se deterna la eejcucion alli y puedas inspeccionar el codigo

    en el articulo uses el clientid del gridview y el img para asignar el click de la opcion que muestra o no el desplegable, el tema es con un tercer nivel esto como lo asignaste ?
    porque no me cierra tan directo para obtener el tr que se cierra, porque no aplicaria sobre el clientid del primer grid sino sobre el segundo


    saludos

    ResponderEliminar
  27. Hola Leandro, gracias por contestar. Siguiendo las pistas que me diste he dado con la solución. Acá te explico cual era el problema.
    Verás tengo la siguiente estructura
    - gvMaestro
    - gvDetalle
    -gvSubDetalle
    Para expandir y colapsar tanto el gvDetalle y gvSubDetalle creé funciones exactas a la de tu ejemplo.
    Esta para el gvDetalle funciona sin problemas
    [code]
    $(function() {

    $('#<%=gvMaestro.ClientID %> img').click(function() {

    var img = $(this)
    var IdMaestro = $(this).attr('IdMaestro');

    var tr = $('#<%=gvMaestro.ClientID %> tr[IdMaestro =' + IdMaestro + ']')
    tr.toggle();

    if (tr.is(':visible'))
    img.attr('src', 'Images/minus.png');
    else
    img.attr('src', 'Images/plus.png');

    });

    });
    [/code]

    En la segunda función sustituyo gvMaestro por gvDetalle, así:
    [code]
    $(function() {

    $('#<%=gvDetalle.ClientID %> img').click(function() {

    var img = $(this)
    var IdDetalle = $(this).attr('IdDetalle');

    var tr = $('#<%=gvDetalle.ClientID %> tr[IdDetalle =' + IdDetalle + ']')
    tr.toggle();

    if (tr.is(':visible'))
    img.attr('src', 'Images/minus.png');
    else
    img.attr('src', 'Images/plus.png');

    });

    });
    [/code]

    Acá el compilador arrojaba el siguiente error: "El nombre 'gvDetalle' no existe en el contexto actual". Ante esto habia optado eliminar la función y dejar el gvSubDetalle siempre visible.

    Siguiendo tu recomendación inspeccioné con ayuda de Firebug y pude notar que el ClienteID que se asigna a gvDetalle nos es simplemente "gvDetalle" sino que aperecía como "gvMaestro_ctl02_gvDetalle"; así que sustituí en la función <%=gvDetalle.ClientID %> por gvMaestro_ctl02_gvDetalle y funcionó a la perfección.

    Aunque me quedé con la espina de no poder extraer el ClientID dinamicamente, gracias a tus sugerencias he resuelto mi problema.

    Ahora bien, ¿Sabes como podría obtener dinamicamente de gvDetalle el ClientID?

    Muchas Gracias.

    ResponderEliminar
  28. Hola leandro en el codigo javascript $('#<%=gvDetalle.ClientID %> img').click(function() ...


    no entiendo muy bien como lo usas ya que el ClientID es parte del archivo js o lo as aumentado? no se si me podrias explicar acerca de eso muchas gracias por tu respuesta

    ResponderEliminar
  29. hola leandro super este tema pero BUSCO ALGO ASI EN WindowsForms!!!

    no he podido encontrar algo de codigo para utilizar datagrid anidados. lo mas cercano a lo que quiero es esto

    http://msdn.microsoft.com/es-es/library/fxfa9793%28v=vs.100%29.aspx
    ya he hecho joins en consultas y llevarlos al dataset, y tambien hacer relations en los Datatable pero no logro hacer que mi datagrid muestre la tabla1 con la tabla2 del link arriba mencionado.

    ResponderEliminar
  30. hola

    no recomendaria usar ese control, si has leido la documentacion el primer parrafo dice muy claro que este control solo se dejo por compatibilidad, que deberias usar el datagridview

    quizas algo como esto:
    Hierarchical DataGridView in C#

    saludos

    ResponderEliminar
  31. HOLA:
    Primero que nada, felicitaciones por tu blog, me gusta como explicas, yo tengo una duda, como se exporta una tabla asi en excel, que guarde los campos principales y a la vez los campos del gridview anidado?Espero contestacion. Saludos!!!

    ResponderEliminar
  32. hola Poulette

    sin usar el excel o las librerias COM de office requiere de algun otro componente como ser

    http://closedxml.codeplex.com/
    o sino
    http://npoi.codeplex.com/

    estos estan basados en openxml por lo que podrias suarlos sin encesidad de office local en la pc donde se debe exportar

    saludos

    ResponderEliminar
  33. hola: gracias por la contestacion, ya los cheque. Ahora me surge otra duda, me podrias dar un ejemplo de como ingresar otro gridview dentro del grid anidado?, por que ya estube checando y no me queda claro como hacerlo, de antemano gracias por tu ayuda

    ResponderEliminar
  34. hola Poulette

    es que la tecnica es la misma que aplicarias al primer grid anidado, solo que la repiten usando el evento RowDataBound pero del segundo grid para localizar dinamicamente al que tendria como hijo

    o sea se repite lo que ya se realizo solo que en un siguiente nivel

    saludos

    ResponderEliminar
  35. hola Oscar

    la verdad no implemente el ejemplo en vb.net

    pero podrias ayudarte con tools como ser

    Convert c#

    para convertir el codigo

    saludos

    ResponderEliminar
  36. Hola Leandro,
    tengo una duda, ambas grillas se deben cargar al mismo tiempo mediante el RowDataBound, de la primera?

    o se pueden cargar dinamicamente, y me refiero con esto a que si se puede clickear un imagebutton, ya sea html o y que al momento de clickear obtengo los datos de la fila y en base a un código contenido en esta me cargue la segunda grilla?

    Saludos

    ResponderEliminar
  37. hola

    como esta planteado en el articulo se cargan a la primera

    podria realizarse alguna carga lazy cuando expandes

    pero si necesitas algo como eso aconsejaria pienses un unsa un mejor control como ser jQGrid

    http://www.trirand.net/demoaspnet.aspx

    analiza el Hierarchy de la demo
    lo descargas de aqui
    jqgrid download


    saludos

    ResponderEliminar
  38. Buen dia Leandro, primero que nada te agradezco por tus post ya que me han servido mucho, tengo una duda acerca de tu tutorial de gridviews anidados, primero que nada uso VB estoy creando una aplicacion donde requiero Maestro - Detalle y la idea de que sea anidado me parece excelente a punta de leer y leer e llegado a cargar la informacion del maestro en la grilla, habilitando la seleccion y edicion mediante dropdownlist, quize pasar al detalle basandome en tu tutorial pero solo logro llegar hasta el punto de agregar los Gif y programar el click ellos mediante jquery, yo uso sqldatasource y Datatables para llenar la grilla, hay manera de adaptar mi necesidad a lo que tu haces en tu tutorial, de ser asi me podrias orientar en que puntos claves debo investigar y estudiar. De antemano gracias :)

    ResponderEliminar
  39. hola Luis

    el tema esta en como resolverias el evento RowDataBound, no se si lo has analizado pero alli se hace uso de una linea muy importante como es

    Order order = (Order)e.Row.DataItem;

    esa linea devuelve la entidad que define la row que se crea en el grid padre, que al estar ya cargado evitas volver a ir a la db para consultar

    quizas si lo haces como planteas en ese punto podrias tomar ltos que se genera y definir el parametro del SqlDatasource del grid relacionado para que genere el filtro para el grid hijo

    o sea de alguna forma en ese evento deberias poder indicar como resolver los datros del grid detalle, creo que se podria realizar, pero esa parte del evento va a cambiar bastante

    saludos

    ResponderEliminar
  40. Buenas tardes Leandro yo aqui molestando de nuevo con 2 consultas, me ha servido de mucho tu ejemplo y te agradezco mucho:
    La primer duda es la siguiente.- No consigo hacer que mediante el click al .GIF se despliegue el TR con el contenido del Gridview Hijo, le quite el display:none y si veo la informacion de todos los gridview hijos correctamente cargada, pero no puedo desplegar o contraer el TR. No se que me pueda estar faltando ya que sigo tu ejemplo.

    Y la otra duda es, que si puedo editar la informacion que esta en el gridview hijo, ya que no he podido abrir los eventos de ese gridview al parecer me marca como si no estuviera declarado ya que se encuentra en un template el gridview padre, no se que fuera necesario para poder hacer esto ya que si necesito editar la informacion del gridview hijo.

    Ya te escribi toda una carta, espero me puedas ayudar y de antemano muchisimas gracias, saludos :D

    ResponderEliminar
  41. hola Luis

    has validado que el evento de javascript se este eejcutando ?

    podrias poner un alert() de javascript o usar el

    debugger;

    para poder detener el codigo y validar que se ejecute el evento

    Poder se puede suar los eventos del gridview hijo, pero si lo realizas desde el diseñador necesitas editar el temaplte

    Using TemplateFields in the GridView Control (C#)

    analiza de la figura 5 a la 7

    saludos

    ResponderEliminar
  42. Buenas tardes Leandro, aqui molestando de nuevo jeje te cuento que ya pude hacer que se contraiga y expanda el Detalle, lo unico que me falta es lo de la edicion en el Gridview Detalle, en la parte del Code Behind solo me aparece el evento SelectedIndexChanged.

    No me aparece el RowDataBound ni ningun otro, que son los que necesito para editar la informacion, no se a que se deba o que me recomiendes hacer, consulte el link que me dejaste en el comentario anterior pero no me quedo muy claro, no se si me explique muy bien.

    De antemano gracias han sido excelente tus tutoriales me han ayudado mucho, y si pudieras orientandome con ese detalle te estaria muy agradecido en verdad.

    ResponderEliminar
  43. Se me olvido decir, que en el Gridview Padre si salen todos los eventos en el Code Behind, en el Gridview Detalle es donde solo me aparece SelectedIndexChanged.

    ResponderEliminar
  44. hola Luis

    si editas el template deberias tener acceso al gridview hijo y a sus eventos

    Tutorial 12: Using TemplateFields in the GridView Control

    analiza las imagens 5 y 6
    al editar el item template accedes al control que este contiene

    saludos

    ResponderEliminar
  45. Hola Leandro buen dia, muchas gracias por tus respuestas, he estado analizando el link que me proporcionaste y no percibo la diferencia o la parte que me falta para poder usar los eventos del Gridview Hijo y asi poder editar su informacion. Si es de un poco mas ayuda te dejo unos screenshots de como se ve mi proyecto.
    En la primer imagen se aprecia que el Grid Hijo esta dentro del Template Field de Padre.
    http://i1274.photobucket.com/albums/y429/rodo0387/1_zps88ee417c.jpg

    En la segunda imagen se aprecia cuales eventos salen para el Grid Hijo.
    http://i1274.photobucket.com/albums/y429/rodo0387/2_zps6781800e.jpg

    No se si con esto pudieras darme un direccion de que hacer o que investigar o bien que otro metodo me convendria usar para realizar lo que necesito, de antemano muchas gracias Leandro, saludos.

    ResponderEliminar
  46. hola Luis

    pero alli no es donde debes ver los eventos, alli solo se listan los eventos que declaraste no los que podes usar

    tenes que ir a la primer imagen que muestras y alli selecciona el grid hijo en la edicion de template

    si vas al cuadro de propiedades veras un icono con forma de rayo amarillo, alli estan los eventos que puedes definir

    pero repito selecciona el grid que esta dentro del template o sea estan do en la priemr imagen que has puesto

    saludos

    ResponderEliminar
  47. Hola Luis, gracias por el articulo.
    Te hago algunas preguntas:
    1) Como hago para recorrer la gridview hijo? Ya que para mi desarrollo necesito guardar en la BD un campo determinado de la tabla hijo.
    2) Agrego un dropdownlist en gridview hijo desde HTML. Ahora quiero llenar los datos que van a dropdownlist desde code behind(c#).
    Como lo puedo implementar?

    Gracias.-
    Slds.-

    ResponderEliminar
  48. hola

    1-
    para recorrer un gridview hijo primero deberias poder seleccionar ese control, lo que no comentas es en que accion estas queriendo realizar esto? pero si tienes la row con la cual trabajar podrias hacer un FindControl() co el nombre del gridview hijo, asi lo localizas y recorres las filas

    foreach(GridViewRow row in GridView1.Rows){

    }

    2-
    esto implicaria el paso anterior mas uno adixional que seria tomasr nuevamente con el FindControl() del dropdownlist, el tema es qe nuevamente no mencionas en que evento quieres lograr esto, si es en el ItemDataBound del grid hijo podrias aplciarlo ya que se da este evento por cada fila, usarias el e.Row y alli buscas por el combo para cagarlo

    saludos

    ResponderEliminar
  49. Gracias Leandro por responderme.

    1)Tengo tabla maestra pregunta y su tabla hija respuesta. Cada respuesta tiene un puntaje. Que de acuerdo al cuestionario puede ir de 0 a 10 o 0 a 100. Entonces el evaluador debe poner la nota(dropdownlist de notas). Entonces debo tomar el idrespuesta(tabla hija) y guardar la nota de acuerdo al idrespuesta.
    Así con todas las respuestas.
    Lo debo hacer en el evento Btn_Guardar_Click(), recorriendo el gridview(hija) y tomando los idrespuesta y notas.

    2) Desde if (!IsPostBack)
    {
    de acuerdo al cuestionario, me traigo las notas de 0 a 10 o 0 a 100
    }
    Luego en el evento gv_preguntas_RowDataBound, de el gridview padre lo lleno:

    Control ctrl = e.Row.FindControl("CmbNotas");

    if (ctrl != null)
    {
    DropDownList dd = ctrl as DropDownList;
    dd.DataSource = DataNotas.Tables[0];
    dd.DataValueField = "Id";
    dd.DataTextField = "Descripcion";
    dd.DataBind();

    }
    Esto anda perfecto, pero me gustaría que este combo este en el gridview hijo, al lado de la respuesta. Luego si todo anda bien, recorrer ese combo, tomar el idrespuesta y grabar en la BD desde un button_click().

    Muchas Gracias.-






    ResponderEliminar
  50. Me auto respondo je:

    1)
    foreach (GridViewRow grd_Row in this.gv_preguntas.Rows)
    {
    GridView GridView2 = (GridView)grd_Row.FindControl("gv_respuestas");
    int idrespuesta = Convert.ToInt32(GridView2.Rows[0].Cells[0].Text.ToString());
    DropDownList notas;
    notas = (DropDownList)GridView2.Rows[0].Cells[2].FindControl("CmbNotas2");
    idnota = Convert.ToInt32(notas.SelectedItem.Value);
    camponota = Convert.ToString(notas.SelectedItem.Text.Trim());

    }

    2) En la gridview hija(HTML), agrego:
    OnRowDataBound="gvChild_RowDataBound"

    En C#:
    protected void gvChild_RowDataBound(object sender, GridViewRowEventArgs e)
    {
    if (e.Row.RowType == DataControlRowType.DataRow)
    {

    Control ctrl = e.Row.FindControl("CmbNotas2");
    if (ctrl != null)
    {
    DropDownList dd = ctrl as DropDownList;
    dd.DataSource = DataNotas.Tables[0];
    dd.DataValueField = "Id";
    dd.DataTextField = "Descripcion";
    dd.DataBind();
    }
    }
    }

    Gracias..Slds.-



    ResponderEliminar
  51. Hola buenas noches y como hago para paginar el gridview que esta dentro del gridview

    ResponderEliminar
  52. genere un código muy similar para vb.net ... yo programado en C# pero ademas en vb .. la lista enlazada no tengo problema pero si tengo que poder interpretar el gvProducts_RowDataBound

    para desplegar el detalle si no no funciona ....

    me puedes hechar una mano
    cambie el GetAllOrdersByCustomer

    el String SQL

    string sql = @"SELECT OrderId,OrderDate,
    RequiredDate,ShippedDate,
    ShipVia,ShipName
    FROM Orders
    WHERE (@customerid = -1 or orderId = @customerid)
    ";

    aunque lo abrias generado como un store procedure ....

    saludos

    zeroyevi@hotmail.com

    ResponderEliminar
  53. hola fernando

    no entendi del todo la problematica, segun veo vas a usar el evento RowDataBound de una tabla de productos, pero que problema hay con la query que planteas?

    parece estar correcta, si desde codigo asignas el parametro deberia retornar los datos para cargar el grid anidado

    recuerda usar el DataKeyNames y DataKeys para tomar el id del producto que usarias de filtro

    saludos

    ResponderEliminar
  54. hola amigo disculpa que te moleste, es que quisiera que me ayudes con algo.
    Tengo un gridview la cual esta lleno de registros de detalles que están vinculados con una cabecera, quiero generar una copia de todos los registros de detalles al momento de generar una modificación para bitacolizar esos registros y asi in activarlos y crear los nuevos registros como activos si me podrias ayudar con algun ejemplo o guiarme como hacerlo te lo agradecería mucho.

    ResponderEliminar
  55. hola Alejandra

    la verdad no se si entendi el planteo, pero si quieres realizar un duplicaod del registro podrias lograrlo directamente en la db creando un trigger

    entonces cuando realizas un cambio en el registro el trigger en sql server este duplicaria el registro en otra tabla de historicos

    saludos

    ResponderEliminar
  56. Hola leandro mira utilice tu ejemplo y en el GridView hijo tengo un button de selecciona pero nunca me dispara el evento ace el posback y nunca entra al evento que debesabes a que se debera de antemano muchas gracias.

    ResponderEliminar
  57. hola Santiago

    estas definiendo algun evento del gridview como ser el RowCommand, porque deberias definir en el boton o link un CommandName

    como asocias el evento del boton a un evento en el codigo .net ?

    saludos

    ResponderEliminar
  58. al final defini el evento onRowComman en el gridView padre padre por que el gridView hijo no me repeto ningun evento...
    Muchas gracias Leandro...

    ResponderEliminar
  59. hola Santiago

    es que el evento deberia ir en el gridview hijo
    por supuesto quizas debas utilizar el sender para saber que grid hijo lanza el evento

    recuerda que si cargas el grid en el evento Page_Load ponerlo dentro del if que valida sino es PostBack

    saludos

    ResponderEliminar
  60. Buenas tardes Leandro, implemente el ejemplo en una aplicacion y funciona perfecto. Uso una pagina maestra y en esta puse un updatepanel y su scriptmanager respectivo, al todo funciona de maravilla la primera vez pero la segunda que recarga la pagina el scrip ya no funciona o sea ya no expande para ver el detalle del grid, he estado buscando y lo que he encontrado es que hay que registrarla, he intentado en el load y en el rowdatabound pero no funciona ademas que al ser una funcion autoejecutable no tengo idea de como llamarla. ¿Podrias ayudarme a solucionar este detalle?
    Gracias.

    ResponderEliminar
  61. hola Gerardo

    el tema es que al usar el UpdatePanel aunque no se actualice toda la pagina la seccion que este abarca si sufre un postback al servidor

    por lo tanto a la vuelta de esta accion deberias volver a re-asignar las acciones de javascript o jquery que hayas definido

    se que no es lo mismo pero analiza

    [ASP.NET] PopUp Filtro – Usando jquery UI Dialog

    veras como alli en el titulo " Re-asignación de evento jquery" sucede lo mismo que planteas

    saludos

    ResponderEliminar
  62. Hola Leandro, una consulta.
    Tome tu ejemplo y le quise agregar la opción de poder seleccionar las filas, intente hacerlo en el evento rowDataBound con este código, pero me alego esto "Sólo se puede llamar a RegisterForEventValidation durante Render();"
    este es el código:

    e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackClientHyperlink(gvOrders, "Select$" + e.Row.DataItemIndex, true));
    e.Row.Style.Add("cursor", "pointer");

    ahora como no funcione, a los GridViews les asigne la propiedad "AutoGenerateSelectButton = true"

    esto funciona con el Grid padre, pero cuando quiero seleccionar una fila del Grid Hijo esta se oculta.

    tienes alguna idea de que puede ser? o de que otra forma se podría hacer?

    saludos

    ResponderEliminar
  63. hola Sebastian

    el tema es que se oculte viene porque al habilitar el AutoGenerateSelectButton este genera un postback al evento, lo cual aplica un render en la pagina, sin importar que este en un updatePanel ya que este tambien se actualiza

    quizas debas usar invocaciones ajax usanndo jquery por medio de $.ajax a webmethods que definas en la pagina
    de esta forma podrias realizar accion y aplicar javascript sin necesidad de eventos de .net, ojo no digo que los selectores que debas definir en jquery vayan a ser simples, pero creo que seria el mejor camino

    saludos

    ResponderEliminar
  64. Leandro muchisimas gracias, el ejemplo es muy util, aunque me costo un poco adecuarlo a lo que tengo.. pero funciona...

    sin embargo, en el gridview anidado necesito utilizar el metodo de edicion del gridview pero al hacerlo colapsa el gridview y luego no deja desplegarla nuevamente... y la verdad ya no se que hacer....

    te agradezco si me puedes ayudar

    mil gracias

    ResponderEliminar
  65. hola Regner

    la verdad mucho no se puede hacer, no si quieres usar evento de asp.net

    quizas deberias usar eventos del lado del cliente usando jquery he invocar webmethods mediante $.ajax() para realizar las acciones sin que se actualice la pagina

    de esta forma no perderias el estado del gridview y sus grid anidados

    el updatepanel no aplica para este caso ya que sigue realizando postback y actualizando la seccion que define

    saludos

    ResponderEliminar
  66. Leandro mil gracias por tu aclaracion.

    ResponderEliminar
  67. Hola Leandro espero no molestarte estoy en mis inicios de VB 2010 el problema es el siguiente tengo un DataGridView en visual Basic en 2010 traje los datos desde una tabla de MySql corre bien los datos se visualizan bien pero cuando doy un clic o doble clic en los titulos de la columna o en la fila me sale error como depurar esto, estas son las lineas de programación para corregir ese error
    Private Sub DgVCategoria_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DgVCategoria.CellDoubleClick
    Dim row As DataGridViewRow = DgVCategoria.Rows(e.ColumnIndex)
    TxtCodigo.Text = Convert.ToString(row.Cells("cod_categoria").Value)
    TxtCategoria.Text = Convert.ToString(row.Cells("categoria").Value)

    End Sub



    cuando utilizo esto
    Dim row As DataGridViewRow = DgVCategoria.Rows(e.ColumnIndex)
    me sale error en las filas cuando doy doble clic en los titulos de las filas

    cuando utilizo esto
    Dim row As DataGridViewRow = DgVCategoria.Rows(e.RowIndex)
    me sale error en la columnas cuando doy doble clic en los titulos de las columnas

    te agradeceria muchisimo
    espero haber sido claro en mi explicación

    Gracias de antemano

    ResponderEliminar
  68. hola Unknown

    si presionas sobre el titulo se lanza la accion peor no hay una row o cell seleccionada
    por lo que deberias al principio del codigo validarlo usando

    If e.RowIndex = -1 Then
    Return
    End If

    o sea si es -1 es porque no hay seleccion por lo que sales sin hacer nada

    saludos

    ResponderEliminar
  69. Hola Leandro una consulta, adapté tu código a VB2010 pero al momento de ejecutar el evento RowDataBound genera el siguiente error "referencia a objeto no establecida como instancia de un objeto", esto sucede en la linea en la que se hace el Ctype para el grid:
    Dim gvDetails As GridView = CType(e.Row.FindControl("GridLicencias"), GridView)

    Por favor sería de gran ayuda tu respuesta. Gracias de antemano.

    ResponderEliminar
  70. hola El Ferna

    ese error se produce porque no puede encontrar el grid que esta dentro del grid
    sino puede encontrarlo entonces deja sin instanciar la busqueda y falla con ese mensaje

    estas seguro que ubicas el grid de detalle de forma correcta?

    saludos

    ResponderEliminar
  71. Hola Leandro Buen dia
    Quisiera si me pudieras orientar a hacer algo parecido a esto pero en visual studio 2010
    Gracias

    ResponderEliminar
  72. hola Jocelyn

    es que no hay diferencia, la version de VS que utilices no afecta, se implementa de la misma forma

    saludos

    ResponderEliminar
  73. Hola
    He visto el link Tutorial 12...
    http://msdn.microsoft.com/en-us/library/bb288032.aspx
    y lo que quiero preguntarte es el grid hijo que sale, lo creas en diseño o mediante escribir codigo?
    y si es en diseño como se hace?, no entiendo el Tutorial. Gracias de antemano

    ResponderEliminar
  74. hola Unknown

    la definicion del grid hijo se realiza desde html en la definicion del TemplateField

    lo que se hace desde codigo es asignar los datos al grid

    saludos

    ResponderEliminar
  75. Hola
    Estoy modificando el ejemplo al conectar con otra base datos y me sale este mensaje
    cuando intento ejecutar la aplicacion. Ahi va el ejemplo Gracias por la respuesta

    Error de servidor en la aplicación '/'.

    Error de compilación

    Descripción: Error durante la compilación de un recurso requerido para dar servicio a esta solicitud. Revise los detalles de error específicos siguientes y modifique el código fuente en consecuencia.

    Mensaje de error del compilador: CS1061: 'System.Web.UI.WebControls.GridView' no contiene una definición de 'IdCliente' ni se encontró ningún método de extensión 'IdCliente' que acepte un primer argumento de tipo 'System.Web.UI.WebControls.GridView' (¿falta una directiva using o una referencia de ensamblado?)

    Error de código fuente:


    Línea 12: $(function () {
    Línea 13:
    Línea 14: $('#<%=gvOrders.IdCliente %> img').click(function () {
    Línea 15:
    Línea 16: var img = $(this)

    ResponderEliminar
  76. hola Unknown

    como comente en la pregunta del foro debes usar:

    $('#<%=gvOrders.ClientID%> img')

    porques lo que buscas son las propiedades del gridview

    saludos

    ResponderEliminar
  77. excelente ejemplo leandro tutini..
    me sirvio mucho.. en verdad...
    solo una pregunta mas..
    se puede hacer un efecto al abrir y cerrar la vista de detalle?
    me refiero a que se cierre mas lento
    y se abra mas lento...
    bueno gracias por todo

    ResponderEliminar
  78. hola Maicol8k

    si usas jquery podrias definir la accion de expandir y colpsar con efecto

    Metodos para realizar animaciones estandar con libreria jquery


    saludos

    ResponderEliminar
  79. una pregunta mas.. el gridviewdetalle puede colocarlo en en un mismo template con una imagen o label?


    label
    imagen
    grilla

    ResponderEliminar
  80. Sirve correctamente solo que tengo un pequeño problema.
    Al ponerlo dentro de un updatePanel
    no realiza la funcion de click alguna solucion?????

    ResponderEliminar
  81. hola Alberto

    el tema es que no se lleva muy bien el updatepanel y jquery
    intenta usar el on() en lugar de definir el click directamente
    jquery on

    saludos

    ResponderEliminar
  82. Hola leandro, quiciera saber si tienes algun ejemplo como este para MVC5 con vs 2013.Ya que estoy empezando en el mundo del mvc y hasta el momento solo he encontrado un ejemplo para mvc4 que no me ha funcionado.

    Saludos cordiales.

    ResponderEliminar
  83. hola Naroven

    la verdad no arme ninguno relacionado con mvc, pero donde trabajo cuando queremoa algo similar usamos jqGrid

    Subgrid as Grid

    lo bueno es que usas json para el source de datos en los grid, con mvc si estas con webapi va genial

    o sino usar DataTable

    Child rows (show extra / detailed information)

    saludos

    ResponderEliminar
  84. Hola Leandro, he leido todos tus aportes y la verdad son muy interesantes, pero tengo una duda o mejor no se como hacerlo.

    Tengo un gridview con una series de columnas y entre ellas una de tipo checkbox y una templatefiel con una imagen, la idea es validar el estado de la columna checkbox para mostrar u ocultar la imagen, como puedo hacerlo, creo que es el el evento RowDataBound del grid, pero no se como hacerlo... cualquier ayuda te lo agradezco...

    ResponderEliminar
  85. Por más que trato de entender el código, no lo consigo. Soy neófito en ASP y programación web. Necesito mostrar un griedview dentro de un gridview de manera fácil.

    ResponderEliminar
  86. hola Claudio

    la verdad una implementacion mas simple que la planteada en este articulo no sabria que aconsejar

    quizas podrias mencionar en que punto tienes problemas asi aporto algun detalle
    pero entiendo que algo deberias entender sobre desarrollo para poder implementarlo, quizas dedicarle un tiempo con algun libro sobre asp.net, o quizas algun video de los tantos que hay en youtube sobre programacion

    saludos

    ResponderEliminar
  87. Hola Leandro, tengo un gridview que muestra en una columna un combo que se llena en el evento RowDataBound, hago la consulta a la base de datos y lleno el combo, ahora bien ¿recomiendas usar una variable de session para guardar la primer vez los datos y en las siguientes filas ya no hacer la consulta a la base de datos?. Ahora estoy consultando cada vez, que recomiendas.
    Gracias

    ResponderEliminar
  88. Leandro por favor se puede usar northwind y pubs en sqlserver express 2014 ?? porq ue a mi me sale un mensaje que no acpeta esta version de base de datos no puede hacer el create database, gracias por tu respuesta

    ResponderEliminar
    Respuestas
    1. hola
      No veo porque no podrias, estas base de datos se crean por medio de scripts
      Deberias poner el mensaje real que recibes, porque la descripcion que mencionas es bastante rara
      La verdad no he usado sql server 2014 por lo que no podria probar lo que comentas
      saludos

      Eliminar
  89. Leandro muchas gracias por tus aportes, tanto en blogs como en MSDN, me han servido bastante :) saludos

    ResponderEliminar
  90. Hola Leandro.
    Gracias por tu aporte y contarte que he adaptado tu ejemplo a mis necesidades, pero en la grilla de detalle le agregue un CheckBox para seleccionar alguno de ellos(detalles) y con ello almacenarlos en un array.

    ResponderEliminar
  91. Hola Leandro soy nuevo en esto, ojalá y puedas ayudarme con este problema, me pidieron hacer un pop up desde un boton, la cosa es que me he estado guiando de un video que es de hace unos años
    y por ejemplo le da click al boton y le sale la opcion agregar extensor desde la tarea del boton lo cual a mi no me aparece, no se si sea por la antiguedad del proyecto seguro es de VS2010 y yo uso 2013, ojalá y puedas ayudarme lo mas antes posible

    ResponderEliminar
    Respuestas
    1. hola
      La aplicacion que estas desarrollando es asp.net ?
      Buscas implementar algo como esto
      [ASP.NET] PopUp Edición - Usando Ajax Toolkit ModalPopupExtender
      o quizas
      [ASP.NET] PopUp Edición - Usando Jquery UI Dialog
      Alli explico como podrias implementar popup
      saludos

      Eliminar
  92. Leandro excelente tu blog estos post aun siguen vigentes porque nos orientan mucho al momento de desarrollar y mira tengo una pregunta de beginners en asp.net pero tengo esa curiosidad y quiero saber que hacen si pongo lo siguiente <%: o <%= o <%# esta ultima veo la usaste en este post para los grid anidados, saludos y gracias de antemano

    ResponderEliminar
    Respuestas
    1. hola
      El uso del <%# solo aplica en los template de los controles como el ListView, GridView, Repeater, etc para bindear el origen de datos que asignes.

      El <%: o <%= la diferencia es si aplica un encode al texto que renderiza
      Are <%: and <%= the same thing as embbed code (expression) blocks
      como veras esto del <%: es nuevo en asp.net 4 y permite encodear el texto cuando se realiza el response

      saludos

      Eliminar
  93. Hola leandro y como logro dejar el grid anidado en visible despues de un postback?

    ResponderEliminar
    Respuestas
    1. Ya lo resolvi con $.ajax si quieren puedo montar el codigo

      Eliminar
    2. hola
      claro el tema es que para dejar visible el grid no puede haber postback
      el $.ajx a un webmethod es una opcion, la otra podrias ser dejar de usar el gridy pasar a un componente basado en javascript como es el jqGrid
      saludos

      Eliminar
  94. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  95. Hola Leandro.
    Me gustaría realizarte unas preguntas. Tengo una capa de acceso a datos, y al traerme las entidades con sus relaciones lo hago con un EntityComposed para armar la entidad con sus relaciones con Linq.
    Estoy viendo en este ejemplo que la manera de conectar las relaciones es llamando a otros métodos, y me parece una manera menos "tediosa" de traerme las relaciones" pero no se si esto hará que se demore mucho en obtener las relaciones.
    1. ¿Cuando te traes las relaciones se realiza una desconexión y conexión para traerte cada relación?
    2. ¿Me recomiendas mantener el EntityComposed?, si me tengo que traer muchas relaciones esto es demasiado tedioso.

    Gracias.

    ResponderEliminar
  96. HOla Leandro, buenos dias, he visto por muchos lugares que apoyas a muchas personas, y en esta ocacion me encuentro en una situacion en donde necesito la ayuda de un experto como tu persona, no se si dispones de tiempo para apoyarme a resolver mi duda, es respecto al uso de ModalPopupExtender, el cual tengo dos paneles y tengo problema que el cargar el asp. Se despliega uno de ellos dentro del formulario(eso no deberia de pasar) y al momento de hacer clic sobre algun otro boton se oculta(como deberia de ser), espero me puedas apoyar. Muchas gracias

    ResponderEliminar
    Respuestas
    1. hola
      Como estas mostrando el popup ? porque quizas la logica del codigo realiza el Show() cuando se carga la pagina

      ASP.NET AJAX Control Toolkit ModalPopupExtender Control in Action

      analiza como en el Panel se define el style="display: none"
      quizas sea eso lo que necesites
      saludos

      Eliminar
  97. Hola Leandro Buenas Tardes

    En esta oportunidad necesita tu apoyo con respecto un tema de GridView Anidados eh logrado realizar la cabecera y detalle, ahora el problema es que quiero acceder al detalle y realizarle un uodate con un foreach pero al querer realizar ello no me reconoce el gridview hijo.


    Este es el padre :
    foreach (GridViewRow dgRow in gvConsProduccion.Rows)
    {
    if (dgRow.RowType == DataControlRowType.DataRow)
    {
    CheckBox chkRow = (dgRow.Cells[27].FindControl("chkRowGen") as CheckBox);
    if (chkRow.Checked)
    {}
    En este caso funciona normal el problema es cuando deseo hacer lo mismo pero con el gridview hijo.
    Te agradeceria mucho tu apoyo en ello
    Gracias
    Atte. Julio Loayza Antunez

    ResponderEliminar
  98. Buenas como le agregas paginado a la grilla hijo?

    ResponderEliminar