domingo, 19 de febrero de 2012

[GridView] Mantener checkbox durante la paginación

 

Introducción

Es bien sabido que asp.net no mantiene estado en muchas de sus operaciones, uno de estos casos podría ser al momento de paginas una lista o grid, es por eso que uno será el responsable de mantener la información que el usuario selecciona.

El artículo demuestra como linq no puede ayudar en esta tarea, para ello contaremos con una interfaz simple que permita paginar una lista de productos.

Diseño del GridView

La creación del GridView no tiene nada especial, solo el uso de una columna de témplate para definir el checkbox

<asp:GridView ID="gvProducts" runat="server" CellPadding="4" ForeColor="#333333" 
    GridLines="None" AllowPaging="True" AutoGenerateColumns="False"  DataKeyNames="Id"
    onpageindexchanging="gvProducts_PageIndexChanging" 
    onpageindexchanged="gvProducts_PageIndexChanged">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:CheckBox ID="chkSelection" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Id" HeaderText="Id" />
        <asp:BoundField DataField="Name" HeaderText="Nombre" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Precio Unitario" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="Unidades Stock" />
        <asp:BoundField DataField="SupplierName" HeaderText="Proveedor" />
        <asp:BoundField DataField="CategoryName" HeaderText="Categoria" />
    </Columns>
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
    <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 destacar en este punto la utilización de dos eventos claves para poder lograr el objetivo de mantener el estado de los check seleccionados por el usuario.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        LoadGridProducts();
    }
}

private void LoadGridProducts()
{
    gvProducts.DataSource = NorthwindData.GetAllProducts();
    gvProducts.DataBind();
}

protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    ProductsSelectionManager.KeepSelection((GridView)sender);

    gvProducts.PageIndex = e.NewPageIndex;
    LoadGridProducts();

}

protected void gvProducts_PageIndexChanged(object sender, EventArgs e)
{
    ProductsSelectionManager.RestoreSelection((GridView)sender);
}

Es justamente en el evento previo a la paginación PageIndexChanging que se guarda el estado actual de los check de la pagina en curso.

Mientras que en el evento posterior a la paginación, PageIndexChenged, o sea cuando se cargo los registros de la pagina a la cual se navega, es que se restablece las marcas que pudiera haber para la misma.

 

Mantener y Restablecer estado checkbox

La implementación de esta funcionalidad esta centrada en la clase ProductsSelectionManager, esta tiene por objetivo no solo contener la lógica que se requiere, sino también encapsular el uso del objeto Session, vital para mantener el estado la información. La idea es que sea algo transparente si se usa el objeto Session o algún otro para mantener el estado.

Los pasos para mantener el estado de los check implican:

  1. recuperar los check marcados de la pagina actual
  2. obtener el estado previo conservado en el objeto Session
  3. comparar los id de producto de la pagina actual con los previos que se tenían en el objeto Session, si alguno esta presente se descarta (esto es necesario porque se conservara el estado actual de la selección para la página, descartando los anterior que estén presente en la lista)
  4. se asignan los id seleccionado a la colección, que se conservara en Session

 

public static void KeepSelection(GridView grid)
{
    //
    // se obtienen los id de producto checkeados de la pagina actual
    //
    List<int> checkedProd = (from item in grid.Rows.Cast<GridViewRow>()
                             let check = (CheckBox)item.FindControl("chkSelection")
                            where check.Checked
                            select Convert.ToInt32(grid.DataKeys[item.RowIndex].Value)).ToList();

    //
    // se recupera de session la lista de seleccionados previamente
    //
    List<int> productsIdSel =  HttpContext.Current.Session["ProdSelection"] as List<int>;

    if (productsIdSel == null)
        productsIdSel = new List<int>();

    //
    // se cruzan todos los registros de la pagina actual del gridview con la lista de seleccionados,
    // si algun item de esa pagina fue marcado previamente no se devuelve
    //
    productsIdSel = (from item in productsIdSel
                     join item2 in grid.Rows.Cast<GridViewRow>()
                        on item equals Convert.ToInt32(grid.DataKeys[item2.RowIndex].Value) into g
                     where !g.Any()
                     select item).ToList();

    //
    // se agregan los seleccionados
    //
    productsIdSel.AddRange(checkedProd);

    HttpContext.Current.Session["ProdSelection"] = productsIdSel;

}

Los pasos para restablecer la selección en la pagina que se visualiza implican:

  1. obtener el estado previo conservado en el objeto Session
  2. comparar los registros de la pagina con los seleccionado, se devuelve las coincidencias
  3. recorrer cada fila del grid que resultara del paso anterior seleccionando el checkbox

 

public static void RestoreSelection(GridView grid)
{

    List<int> productsIdSel = HttpContext.Current.Session["ProdSelection"] as List<int>;

    if (productsIdSel == null)
        return;

    //
    // se comparan los registros de la pagina del grid con los recuperados de la Session
    // los coincidentes se devuelven para ser seleccionados
    //
    List<GridViewRow> result = (from item in grid.Rows.Cast<GridViewRow>()
                                    join item2 in productsIdSel
                                    on Convert.ToInt32(grid.DataKeys[item.RowIndex].Value) equals item2 into g
                                 where g.Any()
                                 select item).ToList();

    //
    // se recorre cada item para marcarlo
    //
    result.ForEach(x => ((CheckBox)x.FindControl("chkSelection")).Checked = true);
    
}

Código

El ejemplo hace uso de una base de datos de Sql Compact 3.5, por eso del archivo .sdf en la carpeta App_Data.

Fue desarrollado usando Visual Studio 2008.

[C#]
[C# SkyDrive]

77 comentarios:

  1. Saludos Leandro!!
    Veo que comienzas el 2012 con el pie derecho, Felicidades nuevamente por tus impresionantes publicaciones...Mi duda es la siguiente, la libreria Linq de asp, trabaja con similitud a querys de sql, en la parte de where mas especificamente, como filtro, es mejor realizarlo en el formulario o seria mas conveniente en la BBDD digamos con un StoreProcedure

    ResponderEliminar
  2. hola IvanKike

    no entedi al pregunta, mas que nada porque linq de asp no existe, linq es parte de .net sin importar la tecnologia que se use

    las queries son similares en la sintaxis a una query de sql, pero no son identicas, solo parecidas

    no entendi si en la parte de where apuntabas a usar linq to sql, quizas en este punto dependa un poco del gusto y la situacion, podrias hacerlo directo en el query de linq y si notas que la performance se degrada verias de pasarlo a un procedure

    saludos

    ResponderEliminar
  3. Buen ejemplo me sirvio un monton...

    ResponderEliminar
  4. Hola Leandro.- te comento he creado botones en ejecución de acuerdo a la cantidad de categorías de producto. Mi pregunta es como poder capturar el Id de la categoría cada vez que hago un clic en dicho botón. para poder otra vez mostrar en botones los productos que pertenecen a esa categoría. Gracias por tu respuesta, es en vb.net 2008

    ResponderEliminar
  5. hola Cleider

    no entendi, esos botones que has creado, donde los ubicas ?

    ademas si hay categorias porque hay botones, no seri mas simple con un combo para seleccion la categoria listada

    saludos

    ResponderEliminar
  6. este codigo me ayudo mucho . Pero ahora tengao un problema yo tengo un boton cancelar y quiero que cuando haga click me haga que todos los checkbox me queden limpios. ya intente haciendo un foreach para el grid pero no me lo realiza en todas las paginaciones del grid me podrian ayudar please.

    ResponderEliminar
  7. hola Guadalupe

    si habras analizado el codigo veras que el truco paramentener la seleccion es por emdio del

    HttpContext.Current.Session

    o sea si en el cancelar haces que el manager elimine la key de la session habras perdido las marcas y por ende no se representaran marcados los check, sino limpias el contenido de la session se volveran a marcar

    saludos

    ResponderEliminar
  8. hola fijece que en el boton cancelar coloco el siguiente codigo para limpiarlos checkbox
    List productsIdSel = HttpContext.Current.Session["ProdSelection"] as List;
    productsIdSel = null;
    pero no se si esta correcto o no comprendido bien como hacerlo, podria ayudarme porfavor.
    Saludos.

    ResponderEliminar
  9. hola, Gracias por el aporte pero ya vi que estaba mal como lo habia colocado y ahora ya me funciona.
    Excelente Blog.
    Saludos.

    ResponderEliminar
  10. quisiera preguntarle si sabe como subir un archivo de access a un grid.
    si tiene alguna idea por favor ayudeme.

    ResponderEliminar
  11. quisiera preguntarle si sabe como subir un archivo de access a un grid.
    si tiene alguna idea por favor ayudeme.

    ResponderEliminar
  12. hola Guadalupe

    por subir te refieres a realziar un upload del archivo?

    o sea usar el control FileUpload, para luego accederlos con ado.net y cargar los datos en el gridview

    analiza

    [ASP.NET] Grabar Archivo en base de datos

    no todo el ejemplo pero si como hacer uso del fileupload para grabar un archivo en una carpeta, toma la primer parte que deja los archivo dentro de una carpeta del sitio

    saludos

    ResponderEliminar
  13. Hola soy principiante ´podrian
    recomendarme un manual de c# por favor

    ResponderEliminar
  14. hola Magaly

    creo que las recomendaciones que brindo aqui

    http://social.msdn.microsoft.com/Forums/es-AR/vcses/thread/645cfa43-3e79-4db5-a516-188654c870e4

    podrian ser de ayuda

    saludos

    ResponderEliminar
  15. hola me arroja un error "El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección.
    Nombre del parámetro: index"

    En esta linea: productsIdSel = (from item in productsIdSel
    join item2 in grid.Rows.Cast()
    on item equals Convert.ToInt32(grid.DataKeys[item2.RowIndex].Value) into g
    where !g.Any()
    select item).ToList();

    ResponderEliminar
  16. hola Scarsx

    cuandos e produce el error has podido obtener o loguear que valor toma el item2.RowIndex
    porque creo que es alli dodne se va de rango

    esto lo digo si es en este codigo que pones donde detectas el problema, aunque quizas sea en otro lugar

    saludos

    ResponderEliminar
  17. hola, fijece que tengo un gridview y necesito que cuando seleccione un dato, poderlo copiar toda la fila seleccionada al portapapeles utilizando el Clipboard, he buscado informacion acerca de como hacerlo pero solo encuentro para datagrid y en codigo java y yo lo necesito en c# y al lado del Code Behind ya que lo estoy realizando en una clase

    ResponderEliminar
  18. hola Guadalupe

    es que no puede ahcer lo que planteas desde c#, porque este es codigo del lado del servidor, no del cliente, se requiere de un postback al server para poder realizar la accion

    o sea deberias ver la forma de hacelro por javascript, para que sea codigo del cliente que se ejecute en el browser

    como planteas desde c# no lo veo viable porque recuerda que el server es comun para todos los usuarios, no hay un clipboard por cada session

    saludos

    ResponderEliminar
  19. tengo un problemita porque en vez de buscar el idex de cada fila le asocio un dataKeys por que quiero que cada fila seleccionada me guarde unos valores de esa fila a una bdd.
    Tengo esto:
    var lista =
    (from item in GvGerentes.Rows.Cast()
    let chbox = (CheckBox)item.FindControl("chboxGerentes")
    where (chbox.Checked)
    select new
    {
    cia = GvGerentes.DataKeys[item.RowIndex].Values["cvecia"].ToString(),
    trab = GvGerentes.DataKeys[item.RowIndex].Values["cvetra"].ToString()
    }
    //Convert.ToInt32(GvGerentes.DataKeys[item.RowIndex].Value)
    ).ToList();

    pero en cada item de la lista me guardar me guarda cia="000002", trab='00002548', y lo que yo quiero es enviar cia y trab para que lo guarde.

    ResponderEliminar
  20. hola miguel

    no has revisado el otro articulo

    [ASP.NET] Mantener información al cambiar de pagina

    creo que se adpata a lo que planteas

    saludos

    ResponderEliminar
  21. Gracias!!! me resolvió el problema que estaba teniendo!

    ResponderEliminar
  22. Que tal Leandro antes que nada se agradece que compartas tus conocimientos muchas gracias, quisiera saber si pudieras hacer un post de como poder ver un GRIDVIEW que NO TENGA DATOS y este en modo de edicion para poder editar y guardar los datos una vez rellenados los campos, no se si me de a entender jaja Saludos

    ResponderEliminar
  23. hola Ger Rojas

    el hecho que un gridview no tenga datos implica que deberia definirse el
    GridView.EmptyDataTemplate (Propiedad)

    pero esto no posibilita la edicion, quizas deberias contar con controles externos que permitan ingresar informacion y al aceptar generar el nuevo registro que se vusuace luego en el grid

    saludos

    ResponderEliminar
  24. Hola Leandro me pasa que selecciono unos checbox de un gridview y al dar click en un boton estos pierden la seleccion o al seleccionar un afecha de un calendar se pierden los datos del gridview como puedo controlar esto uso la opcion if(!ispostback)
    pero desps pierdo los checbox al dar click en el boton

    ResponderEliminar
  25. hola Gato NvZ

    pero no has analizado lo que plantea el articulo, porque esta misma tecnica se aplica a la paginacion o a cualquier otra accion

    quizas este otro lo complemente

    [ASP.NET] Mantener información al cambiar de pagina

    saludos

    ResponderEliminar
  26. Master, buenas tardes
    Quisiera saber si podria ayudarme con este mismo ejemplo pero en .net
    el checkbox en un datagridview y al marcarlo cambiarlo de color.

    Favor de su ayuda.

    ResponderEliminar
  27. hola Seraúl

    pero este ejemplo apunta a un entorno web, no desktop

    estas paginando un DataGridView? la tecnica podria ser parecida en cuanto al linq para realizar los merge, pero en winforms la Session no se necesita

    saludos

    ResponderEliminar
  28. Hola Leandro mira tengo un problema me arroja error al mostrar un gridview con base de datos .sdf 3.5
    con lenguaje vb.net me arroja el Error de servidor en la aplicación '/'.
    No se encuentra el proveedor de datos .NET Framework solicitado. Puede que no esté instalado.

    pero si yo realizo una consulta a la base de datos me trae el dato sin problemas a un textbox.

    ResponderEliminar
  29. hola Roberto

    cuando dices que realizas una consuta y trae los datos desde donde estas realizando esta prueba ?

    ejecutas la aplicacion desde el VS, o lo estas montando en el iis

    saludos

    ResponderEliminar
  30. Oye gracias por la solución pero lo estoy haciendo en vb y me genera conflicto en el Into así tengo el código:

    productsIdSel = (From item In productsIdSel
    Join item2 In grid.Rows.Cast(Of GridViewRow)()
    On item Equals Convert.ToInt32(grid.DataKeys(item2.RowIndex).Value) Into g Where Not g.Any() Select item).ToList()

    ResponderEliminar
  31. hola Javier

    algo que veo raro es como armas el Equals
    se supone que se deberia compara alli el item con item2, es similar a un JOIN que harias en sql contra una db

    no usas el grid que no se de donde salio, sino que usas el item2

    saludos

    ResponderEliminar
  32. Hola Leandro.
    Gracias por contestar.

    Lo que yo hice fue transcribir la línea de código del método keepselection a vb exactamente como tu la tienes en C# me dices que no uso el grid y mira que si comparo item con item2 en el equals:

    On item Equals Convert.ToInt32(grid.DataKeys(item2.RowIndex).Value) Into g Where Not g.Any() Select item).ToList()

    Tu código:
    on item equals Convert.ToInt32(grid.DataKeys[item2.RowIndex].Value) into g
    where !g.Any() select item).ToList();

    Espero me puedas ayudar.

    Gracias.

    ResponderEliminar
  33. hola Javier

    pero cual seria exactamente el error que menciona

    porque una cosa es no suas y otra muy distinta es que no este declarado
    recuerda que el "grid" hace referencia al control GridView de la apgina que se pasa por parametros en el metodo KeepSelection()

    saludos

    ResponderEliminar
  34. Hola Leandro tengo el mismo problema que Javier al usar un convertidor de C# a VB el código Linq me genera algunos errores con algunas cláusulas como Into y otros.

    Me parece que el problema está en la sintaxis del código Linq en VB.

    No soy muy bueno usando Linq.
    Agradecería tu ayuda.
    Saludos.

    ResponderEliminar
  35. hola Amado

    LINQ Query Samples - Grouping Operators

    en lugar de Into g
    no probaron utilizar: Into Group

    porque creo que vb.net requiere que se use ese nombre, como se ejemplifica en el link

    saludos

    ResponderEliminar
  36. Hola Leandro.

    Como menciona Amado el error sale en el Into cuando cierras el parentesis del Value Convert.ToInt32(grid.DataKeys(item2.RowIndex).Value) no lee el Into y el Into Group solo lee el Group.

    Espero nos puedas ayudar.

    Gracias.

    ResponderEliminar
  37. hola Javier

    claro pero se supone que es un join que usas para implementar el join

    pero lo que devuelves en el select es el item

    cual es el mensaje de error que se genera ?
    y como es el linq que definen

    saludos

    ResponderEliminar
  38. Hola Leandro

    El código lo tengo así:

    productsIdSel = (From item In productsIdSel
    Join item2 In grid.Rows.Cast(Of GridViewRow)()
    On item Equals Convert.ToInt32(grid.DataKeys(item2.RowIndex).Value) Into Group Where Not g.Any() Select item).ToList()

    El error que sale es:

    Error 16 ')' expected.

    Si se cierra pues no lee el resto del código.

    Gracias.

    ResponderEliminar
  39. hola Javier

    no probaste si al definir cada linea del linq usas un _

    porque vb.net requiere usar los _ para cada linea

    productsIdSel = (From item In productsIdSel _
    Join item2 ...

    saludos

    ResponderEliminar
  40. Hola Leandro antes que nada gracias porque me ayuda mucho tus publicaciones aciertas en mis obstaculos del dia a dia, bueno te escribo porque tengo poco tiempo en .net y tengo un problemita necesito seleccionar varias filas de un gridview eso ya lo logre con lo que tu explicaste pero lo que necesito ahora es que estas filas seleccionadas pueda filtrarlas en otro gridview te agradezco de antemano tu atención a mi solicitud espero puedas ayudarme

    ResponderEliminar
  41. hola Elsa

    en ese caso imagino podrias usar la instruccion IN de un SELECT que ejecutes

    la unica macana es que no se puede usar parametros con el IN, sino que se arma dinamicamente un string con cada valor separado poc comas

    IN (Transact-SQL)

    saludos

    ResponderEliminar
  42. Muchas gracias por responder si Leandro eso ya lo tengo armado me explicare mejor el detalle es que siguiendo tu ejemplo de mantener el estado de checkbox si uso selectedindexchanged me da error no me carga mi pagina no se como resolverlo gracias por tu interes

    ResponderEliminar
  43. hola Elsa

    es que no deberias usar el selectedindexchanged de los check, sino que deberia suar alguna otra opcion para tomar todos los check marcados para armar el filtro

    y si usas el selectedindexchanged seguro debas aplicar el NamingContainer para conocer el GridViewRow que contiene el check que lanza la accion

    cuando dices que se produce un error cual seria el mensaje?

    si notas que es un tema que podria llevar varios mensajes se podria seguir en el foro de asp.net

    asp.net foro

    saludos

    ResponderEliminar
  44. Hola gracias Leandro, ya escribi mi consulta en el foro espero me puedan ayudar aqui dejo el link a mi pregunta http://social.msdn.microsoft.com/Forums/es-ES/netfxwebes/thread/1228dc62-1082-4ecc-b2df-fd2c0dfe895f gracias

    ResponderEliminar
  45. hola Elsa

    respondi en la pregunta del foro

    saludos

    ResponderEliminar
  46. Hola Leandro,
    Antes que nada gracias por el post.
    Tengo una duda, estoy intentando implementar la paginación pero en vez de que sea con checkbox es con un textbox :S
    He intentado adaptar el código, pero presento un problema especificamente con esta linea:

    result.ForEach(x => ((CheckBox)x.FindControl("chkSelection")).Checked = true);

    Por que en mi caso, ahí debería es de asignarle el string que tenía la caja de texto y no un valor booleano.

    Depronto sabes que consideraciones debo de tener en cuenta ?

    Muchas gracias !

    ResponderEliminar
  47. hola

    pero no analizaste el otro articulo que esta arriba de este

    [ASP.NET] Mantener información al cambiar de paginacion

    este define textbox y combo para mantener datos cuando paginas
    quizas se adapte a lo que quieres lograr

    saludos

    ResponderEliminar
  48. muy buen articulo amigo muchas gracias por compartir el conocimiento un hombre culto no es solo el que sabe sino el que ademas de saber lo comparte exitos

    ResponderEliminar
  49. Leandro, muchas gracias por compartir tus conocimientos con nosotros. Te estoy eternamente agradecido por todos los articulos.
    Ahora te quiero consulta una duda, hice todo lo que pones para mantener los checks, pero cuando se realiza el "RestoreSelection" me sigue tomando la pagina de la grilla anterior, es decir chekeo las opciones, grabo los checks de la pag. 1, paso a la pagina 2, vuelvo a la pagina 1 y cuando vuelvo en el evento "PageIndexChanged" al querer leer la gridview todavia me sigue leyendo los valores de la pagina2 a que puede deberse esto? nose que estoy haciendo mal.
    Espero que se haya entendido. Saludos!!

    ResponderEliminar
  50. hola Gabriel

    imagino que el restore lo realizas despues de asignar el index de la pagina y del datasource del gridview, realizando el Databind(), luego de eso es que aplicar el restore de los checks ?


    saludos

    ResponderEliminar
  51. Gracias por la rapida respuesta!

    Si, estoy haciendo exactamente eso.
    Nose que pueda ser, cuando llega al metodo "gvProducts_PageIndexChanged", la pagina que tiene es la anterior, no la que hace en el databind, nose porque pueda pasar.

    ResponderEliminar
  52. hola Gabriel

    pero al paginar asignas


    gridview1.PageIndex = e.NewPageIndex;
    gridview1.DataSource = datos;
    gridview1.DataBind();

    o sea en el paginado debes asignar la pagina y ademas volver a poner los datos

    saludos

    ResponderEliminar
  53. Hola, muchas gracias por tu aporte.. siempre nos encontramos con este tipo de problema cuando estamos desarrollando, y si bien había ocupado otras soluciones, esta ha sido la mejor que he encontrado.. MUY buen aporte. Saludos.

    ResponderEliminar
  54. buenos dias leandro.

    mi duda es porque al cambiar de pagina en mi gridview no me respeta el check de la pagina anterior? estoy haciendo algo mal o que onda es decir que check en pagina 1 despues check en pagina 2 regreso y no mantiene el check, sabes porque ?

    ResponderEliminar
  55. hola Unknown

    la informacion de los checkbox donde la persistes cuando navegas de una pagina a otra ?
    porque recuerda que el estado no se mentiene, deberias tomar la seleccion y usar el objeto Session para conservarla

    saludos

    ResponderEliminar
  56. Hola Leandro muy bueno tu ejemplo,
    No se si podras postearlo en VBasic por favor te lo agradeceria ..

    Saludos
    Diego Castillo

    ResponderEliminar
  57. hola Diego

    no te animas a usar alguna tool como ser:
    http://converter.telerik.com/

    o sino:
    http://www.icsharpcode.net/opensource/sd/

    este es un IDE open source que tiene opciones para convertir proyectos completos de un lenguaje a otro

    intenta con esas tool, pero si hay algo en concreto que no se puede convertir avisame y lo analizamos

    saludos

    ResponderEliminar
  58. Hola Leandro!

    quisiera saber como recorrer un gridview y saber cuales son los checkBox que estan seleccionados y a su vez almacenarlos en una DataTable.

    Si me puedes ayudar te lo agradezco mucho!!

    Muchas gracias por compartir tu conocimiento, me ha sido de gran ayuda tu Blog!

    ResponderEliminar
  59. hola Maleja

    imagino programas en c#, si es asi aqui

    http://social.msdn.microsoft.com/Forums/es-ES/85f43151-8144-42d4-9ed8-abf691136122/guardar-informacion-de-gridview-desde-checkbox

    respondo la misma pregunta, veras que en un foreach recorro las rows del grid y se valida si el control check esta marcado

    para volcar esto a un datatable solo es cuestion de crear las row nueva usando

    DataRow row = dt.NewRow();
    row["NombreCol1"] = valor;
    row["NombreCol2"] = valor;
    dt.Rows.Add(row);

    saludos

    ResponderEliminar
  60. Muy buen post Leandro me sirvio mucho.

    ResponderEliminar
  61. Hola Leandro,
    Como se haria en el caso de tener mas de un DataKeysNames??

    mi caso es:
    DataKeyNames="IdOferta,CódigoArtículoProveedor,WebURL"
    siendo IdOferta la clave primaria...

    Saludos.

    ResponderEliminar
  62. lenadro me podrias ayudar con este pequeno codigo : :(
    tengo una aplicacion, en la cual puedo leer el texto de de un checkbox de otra aplicacion externa, pero no he podido encontrar la forma de saber si ese check box esta activo o no, el codigo para poder leer el texto por medio de su ID (handle)es:


    PrivateDeclareFunctionSendMessageTimeoutStringLib"user32"Alias"SendMessageTimeoutA"(ByValhwndAsInteger,ByValmsgAsInteger,ByValwParamAsInteger,ByVallParamAsString,ByValfuFlagsAsInteger,ByValuTimeoutAsInteger,ByReflpdwResultAsInteger)AsInteger



    Private

    FunctionGetText2(ByValhwndAsInteger)AsString

    DimsTextAsString



    sText = Space(1024)

    GetText2 = vb.Left(sText, InStr(sText, vbNullChar) - 1)

    EndIf

    ReturnGetText2

    EndFunction

    Private

    SubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load

    textbox1.Text = GetText2(66220)
    end sub
    ifSendMessageTimeoutString(hwnd, WM_GETTEXT, 1024, sText, SMTO_ABORTIFHUNG, 1000, 0) <> 0 Then

    ResponderEliminar
  63. hola Vladimir

    la verdad nunca trabaje con las api de windows para acceder a aplicaciones externas

    aqui
    getting text entered in textbox of other applications using c#

    acceden a los textbox de uan aplicacion externa, quizas cambiando de control se podria aplicar la misma tecnica
    saludos

    ResponderEliminar
  64. hola leandro... gracias por los tutoriales están buenos.

    te comento tengo un problema al pasarlo a vb.net
    la parte de :

    productsIdSel = (from item in productsIdSel join item2 in grid.Rows.Cast()on item equals Convert.ToInt32(grid.DataKeys[item2.RowIndex].Value) into g where !g.Any() select item).ToList();

    me sale esto:

    productsIdSel = (From item In productsIdSel Join item2 In grid.Rows.Cast(Of GridViewRow)() On item Equals Convert.ToInt32(grid.DataKeys(item2.RowIndex).Value) into g Where Not g.Any()item).ToList()

    en la parte de into me sale el problema nose si me puedes echar una mano te lo agradecería bastante

    ResponderEliminar
  65. Hola Leandro, una consulta:

    Estoy paginando una grilla, la cual tiene varias paginas y debo validar que al menos 1 registro sea seleccionado. Utilizo las funciones mantener y restaurar seleecionados guardando las selecciones en una variable de sesion. Sin embargo, no se me ocurre como saber si hay algun item seleccionado, ya que si hago un foreach, solo recorro los registros de la pagina actual, y la variable de sesion me devuelve null porque no estoy cambiando de pagina.

    Gracias!!

    ResponderEliminar
  66. hola Cristian

    pero porque no trabjas con los datos que guardaste en la session directamente

    si la ides es validar si hay algo marcado vuelva lo que tienes en la pagina actual a la session uniendolo a lo que tienes que otras paginas y continuas usando la session, no necesitas validar contral el gridview

    saludos

    ResponderEliminar
  67. Grande Leandro, como siempre tus respuestas me salvan la vida.

    Modifique un toque tu codigo para que sea aplicado a TextBox, la idea era que se omita el btn de edit/update del gridview y que se pueda escribir en todos los textbox de una columna y abajo del grid un btn actualizar que hacia todo.
    Se me perdia la data al hacer el paginado.-

    En concclusion; salio todo perfecto! Grac

    ResponderEliminar
  68. Que tal Leandro soy novato en programación he tratado de adaptar tu código a un ListView pero no he tenido éxito, podrías ayudarme? intento hacer lo mismo tengo unos checbox paginados en un listview cuando cambio de pagina pierdo los seleccionados anteriormente. espero puedas ayudarme. Gracias de ante mano por toda esta información

    ResponderEliminar
  69. hola Felipe

    entiendo que el ListView no deberia ser muy diferente al GridView salvo quizas por la forma en que accedes al checkbox

    en el listview no tienes rows sino que tienes items por lo que usarias

    xx.Item.FindControl("nombrecheck")

    estas usandolo de esa forma?

    saludos

    ResponderEliminar
  70. Hola Leandro,
    Estaba intentando implementar tu código pasándolo a vb.net pero no consigo que me funcione, es muy probable que no lo haya convertido bien a vb.net ya que no lo manejo nada pero me obligan a utilizarlo.
    Te detallo como lo estoy implementando

    Protected Sub GridViewLibros_PageIndexChanged(sender As Object, e As EventArgs)
    restoreSelection(CType(sender, GridView))
    End Sub

    Protected Sub GridViewLibros_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)

    keepSelection(CType(sender, GridView))
    GridViewLibros.PageIndex = e.NewPageIndex
    fillGrid(sqlBase)

    End Sub


    Protected Sub keepSelection(ByVal mGridView As GridView)

    'Obtenemos los ids seleccionados
    Dim checkedLib As List(Of String) =
    (From item In mGridView.Rows.Cast(Of GridViewRow)() Let check = DirectCast(item.FindControl("chkSelec"), CheckBox)
    Where check.Checked Select Convert.ToString(mGridView.DataKeys(item.RowIndex).Value)).ToList()

    'Recuperamos la sesion previamente guardada
    Dim idSelec As List(Of String) = HttpContext.Current.Session("ListaSeleccionados")
    If IsNothing(idSelec) Then
    idSelec = New List(Of String)

    End If

    '
    idSelec = (From item In idSelec
    Join item2 In mGridView.Rows.Cast(Of GridViewRow)() On item Equals Convert.ToString(mGridView.DataKeys(item2.RowIndex).Value)
    Where (item.Any()) Select item).ToList()

    'guardamos
    idSelec.AddRange(checkedLib)
    HttpContext.Current.Session("ListaSeleccionados") = idSelec
    End Sub

    Protected Sub restoreSelection(ByVal mgridView As GridView)
    Dim idSelec As List(Of String) = HttpContext.Current.Session("ListaSeleccionados")
    If IsNothing(idSelec) Then
    Return
    End If

    'Cogemos los seleccionados
    Dim resul As List(Of GridViewRow) = (From item In mgridView.Rows.Cast(Of GridViewRow)() Join item2 In idSelec On
    Convert.ToString(mgridView.DataKeys(item.RowIndex).Value) Equals item2 Where (item2.Any()) Select item).ToList()

    resul.ForEach(Function(x) InlineAssignHelper(DirectCast(x.FindControl("chkSelec"), CheckBox).Checked, True))
    End Sub


    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
    target = value
    Return value
    End Function


    A ver si me puedes echar una mano.
    Gracias y un saludo

    ResponderEliminar
  71. hola Guillermo

    lo que veo incorrecto es la definicion de InlineAssignHelper

    pero en que lugares marca error el codigo?


    saludos

    ResponderEliminar
  72. Estimado, no hay un enlace para descargar el ejemplo??

    ResponderEliminar
  73. Hola Leandro, implemente tu código pero necesito poner un botón que copie los registros seleccionados a otra grilla y no me esta saliendo. En base a tu ejemplo me podrías dar una mano? Gracias, gabriela

    ResponderEliminar