sábado, 20 de febrero de 2010

C# - JQuery - GridView, detectar selección checkbox

 

Introducción

La razón de este ejemplo es poder detectar la selección individual de cada checkbox introducido en una columna de la grilla y ante la marca de al menos un check poder habilita la acción de cierto un botón. Todo esto del lado del cliente.

 

Código JavaScript

Para esta operación nos ayudaremos de la librería jQuery.

La misma podrá apreciarse que ha sido incluida mediante la referencia de la primer línea del código del ejemplo.

<script src="js/jquery-1.4.2.min.js" type="text/javascript"></script>

<script language="javascript" type="text/javascript">

    $().ready(function() {


        $("#<%=GridView1.ClientID%> :checkbox").click(function() {

            var seleccionado = false;

            $("#<%=GridView1.ClientID%> :checkbox").each(function() {

                if (this.checked)
                    seleccionado = true;

            });

            var botondeshabilitar = $("#<%=btnEnviar.ClientID%>");
            
            if (seleccionado)
                botondeshabilitar.removeAttr('disabled');
            else
                botondeshabilitar.attr('disabled', 'disabled');

        })


    });

</script>

La instrucción $().ready(function(){..}) (línea 5) nos brindara la seguridad que el código que incluyamos allí dentro será ejecutado ni bien este disponible el objeto document de javascript.

Esto es importante ya que dentro de este estamos accediendo a los controles y es necesario hacerlo de forma segura.

Con $(..).click(function(){}), (línea 8) estamos seleccionado todos los checkbox que contenga el grdiview, y adjuntando el evento click, debe recordarse que este evento se agregara a cada control checkbox de forma individual.

Cada vez que es presionado un checkbox se evalúan todos los check en conjunto para saber si hay algún otro seleccionado o no, en caso de haber uno se deje habilitado el botón, en cado de no quedar ninguno se deshabilita.

La forma de recorrer cada ítem seleccionado $().each(function(){}), (línea 12), evalúa el estado del check de ese ítem en particular modificando la variable que se encuentra declarada fuera de esta función. Debe remarcarse que el “this” que se usa dentro del each es un objeto de javascript clásico, no es un objeto de jquery, es por eso que se usa directamente la propiedad “checked”, esta es de javascript, no de jquery.

Algo que seguro se preguntaran es porque en la líneas 8 y 12 se realiza la misma selección y no se reemplaza la segunda por un this. Esto se debe a que al adjuntar el evento al click este lo hace de forma individual, razón por la cual es this dentro del click representa un solo control checkbox, y no todos, haciendo necesario nuevamente la selección, para poder realizar el ciclo y evaluación de estado.

Hay que mencionar que es importante la forma en como se selecciona los controles de asp.net usando <%=%> (ejemplo línea 19), como se notara al renderizar un control de asp.net este cambia el id asignado por otro, para que tenga el control un identificador único, es por eso que lo correcto al trabajar con controles se utilice la propiedad ClientID.

[C#]
 

15 comentarios:

  1. Leandro muy bueno el post, lo he probado y pincha bien, ahora cuando hay paginación en el GridView deja de funcionar, sabes porque???
    Bueno saludos Oscar

    ResponderEliminar
  2. hola Oscar Hdez

    cuando dices que deja de funcionar te refieres a que no marca los check que estan visibles en la pagina que visualizas en el grid ?

    recuerda que jquery se aplica en el cliente y al marcar el check cuando se pagina este solo actuara con los check de la pagina actual, por solo esos se estan visualizando

    si necesitas marcar todos quizas debas trabajar directo con el origen de datos y no con el grid

    saludos

    ResponderEliminar
  3. Hola Leandro.
    Ante todo gracias por mostrar interes en ayudarme.
    Cuando digo que deja de funcionar es que cuando tengo paginación y paso a la segunda pagina del GridView marco algun checkbox y lo desmarco y bueno no se ejecuta la acción sobre el boton de habilitarlo y desabilitarlo.
    Si no cambio de pagina en el GridView si trabaja bien, es decir se habilita el boton y se desabilita cuando marco un checkbox y lo desmarco.
    Sabes porque pasa eso???
    Espero que entiendas lo que quiero decir. Saludos Oscar

    ResponderEliminar
  4. hola

    de casualidad estas usando el UpdatePanel, o sea se ejecuta la paginacion, pero no hay un refresh de la pantalla ?

    lo pregunto porque en ese caso es logico que ocurre, recuerda que el updatepanel sigue usando el postback al servidor solo que tu no notas el refresh, entonces cuando vuelve al no recargar la pagina los eventos de jquery no se reasociaron con el nuevo html que cambio

    deberas forzar esto enviando codigo javascript que vuelva hacer pasar por ready(), pero primero veamos que sea este el problema.

    saludos

    ResponderEliminar
  5. Leandro:
    Me habia dado cuenta de eso que me comentas leyendo algunos foros en internet, y como usted dice cuando hay un postback los eventos del JQuery se desvinculan y lo que hice fue poner en el evento Page_Load el llamado "ScriptManager.RegisterStartupScript(...);" y con eso me trabaja de maravillas.
    Muchas gracias por su ayuda, me ha sido muy util, con un blog como el de usted es fácil enfrentar cualquier obstaculo en el mundo de la programación. Saludos Oscar

    ResponderEliminar
  6. Tengo varias columnas con check, como haria

    ResponderEliminar
  7. hola Urbano Palomino

    disculpa la tardanza

    bien en este caso se me ocurre que podrias definir un class para cada checkbox usando este en la seleccion con jquery, o sea usarias

    $("#<%=GridView1.ClientID%> .nombreclass")

    veras que aqui uso el punto para seleccionar por class, no se hace por tipo

    por supuesto el check deberia ser

    <asp:CheckBox ID="CheckBox1" runat="server" CssClass="nombreclass" />

    a cada check le pones un class diferente para saber con cual trabajar

    saludos

    ResponderEliminar
  8. Leandro:
    Esta muy bueno el post y creo que me puede servir, pero tengo una consulta. Tengo un Gridview dentro de un modalpopup de jQuery, y los eventos que estan en el code behind de la grilla no se ejecutan. Como puedo yo, bajo estas circunstancias, poder identificar la fila de la grilla a la que hago referencia mediante un control imagebutton dentro de la grilla?

    ResponderEliminar
  9. hola slean1

    de casualidad no estas usando el control UpdatePanel ?

    con este podrias seguir usando los evento del gridview, pero sin que se refresque la pantalla, por lo tanto el popup no se cerrara

    de esta forma podrias usar la seleccion de grid como la conoces y a la vez jquery

    saludos

    ResponderEliminar
  10. Efectivamente, estoy usando UpdatePanel, pero aún asi, estando dentro del modal popup de jQuery, el click que está programado para el botón de la grilla no llega al code behind, ese es mi problema

    ResponderEliminar
  11. hola slean1

    pero este boton del grid tiene definido los evento de seleccion, como se explica aqui

    [ASP.NET][GridView] - Como seleccionar una fila

    ademas es un boton o link de asp.net el que usas en el grid, no ?

    prueba de llevar este grid a nivel de pagina, sacadlo del popup, o del UpdatePanel y valida que funcione correctametne, luego agregalo a updatepanel y que siga funcionando, luego agregalo a popup

    saludos

    ResponderEliminar
  12. Leandro:
    Se perfectamente como se programa un botón en la grilla. Al parecer no me has comprendido, y pido disculpas si no he podido aclarar la situación. La grilla fuera del popup de jQuery funciona bien, pero una vez que la pongo dentro de un div que funciona como modal popup con jQuery, deja de ejecutar todo el code behind programado para la grilla. Ese es mi problema y espero haberme explicado mejor. Gracias por el tiempo y por las respuestas.

    ResponderEliminar
  13. Gracias por vuestra ayuda, pero lo haré con jSon.

    Gracias

    ResponderEliminar
  14. Hola Leonardo

    quisiera preguntarte

    lo que quiero es traer un dato de la base de datos, cuando ejecuto el boton Button1_Click me trae en un textbox,
    esto dentro del textbox
    ////FACTURACION2015.ObjetosdelNegocio.Cliente//// y no me trae el atributo sino el objeto.


    primero en la vista

    protected void Button1_Click(object sender, EventArgs e)
    {
    cliente.Nombre = txtNombreCliente.Text;
    TextBox1.Text = Convert.ToString(ClienteCtl.ConsultarPorNombre(cliente));
    }

    en el controlador
    public static Cliente ConsultarPorNombre(Cliente cliente)
    {
    return ClienteBD.ConsultarPorNombre(cliente);
    }


    en el accesob a datos

    public static Cliente FillDataRecord1(IDataRecord myDataRecord) //llenar datos de registros
    {
    Cliente miCliente = new Cliente();

    miCliente.Nombre = myDataRecord.GetString(myDataRecord.GetOrdinal("NOMBRE"));

    return miCliente;
    }

    public static Cliente ConsultarPorNombre(Cliente cliente)
    {
    Cliente miCliente = new Cliente();

    using (SqlConnection myConnection = new SqlConnection(appConfiguration.ConnectionString))
    {
    SqlCommand myCommand = new SqlCommand("OBTENERCLIENTEbynombre", myConnection);
    myCommand.CommandType = CommandType.StoredProcedure;
    myCommand.Parameters.AddWithValue("@nombre", cliente.Nombre);

    myConnection.Open();
    using (SqlDataReader myReader = myCommand.ExecuteReader())
    {
    if (myReader.Read())
    {
    miCliente = FillDataRecord1(myReader);
    }
    myReader.Close();
    }
    myConnection.Close();
    }
    return miCliente;
    }

    me podrias ayudar, quiero traer solo un dato de la bases de datos y almacenarlo en un textbox
    gracias

    ResponderEliminar
  15. hola Ervin

    pero deberias usar

    protected void Button1_Click(object sender, EventArgs e)
    {
    cliente.Nombre = txtNombreCliente.Text;

    Cliente cli = ClienteCtl.ConsultarPorNombre(cliente);
    TextBox1.Text = cli.Nombre;
    }

    o sea recuperas la entidad y de esta la propeidad
    igualmente veo raro que solo recuperes el nombre cuando defines el FillDataRecord1() y el resto de las propeidades ?

    ademas porque en ConsultarPorNombre() pasas toda una entidad si solo vas a usar la propiedad nombre, no tiene mucho sentido, defiens un parametro simple del tipo string y listo
    ahora si haces un filtro generico que puede filtrar por varios atributos alli si se justificaria

    saludos

    ResponderEliminar