Agregar una columna GridView de casillas de verificación (C#)

por Scott Mitchell

Descargar PDF

En este tutorial se explica cómo agregar una columna de casillas a un control GridView para proporcionar al usuario una manera intuitiva de seleccionar varias filas de GridView.

Introducción

En el tutorial anterior hemos examinado cómo agregar una columna de botones de radio a GridView con el fin de seleccionar un registro determinado. Una columna de botones de radio es una interfaz de usuario adecuada cuando el usuario está limitado a elegir como máximo un elemento de la cuadrícula. Pero en ocasiones, es posible que quieras permitir al usuario elegir un número arbitrario de elementos de la cuadrícula. Por ejemplo, los clientes de correo electrónico basados en la web muestran la lista de mensajes con una columna de casillas. El usuario puede seleccionar un número arbitrario de mensajes y, a continuación, realizar alguna acción, como mover los correos electrónicos a otra carpeta o eliminarlos.

En este tutorial veremos cómo agregar una columna de casillas y cómo determinar qué casillas se activaron en postback. En concreto, crearemos un ejemplo que imita fielmente la interfaz de usuario del cliente de correo electrónico basado en la web. En nuestro ejemplo se incluirá una clase GridView paginada en la que se enumeran los productos de la tabla de la base de datos Products con una casilla en cada fila (vea la figura 1). Y un botón de Eliminar productos seleccionados, que eliminará esos productos seleccionados al hacer clic en él.

Each Product Row Includes a Checkbox

Figura 1: Cada fila de producto incluye una casilla (haz clic para ver la imagen a tamaño completo)

Paso 1: Agregar un control GridView paginado que enumera la información del producto

Antes de preocuparnos de agregar una columna de casillas, nos centraremos en enumerar los productos en un GridView que admita la paginación. Para empezar, abre la página CheckBoxField.aspx en la carpeta EnhancedGridView y arrastra un control GridView desde el Cuadro de herramientas al Diseñador, y establece sus ID en Products. A continuación, elige enlazar GridView a un nuevo ObjectDataSource denominado ProductsDataSource. Configura ObjectDataSource para usar la clase ProductsBLL, llamando al método GetProducts() para devolver los datos. Como este control GridView será de solo lectura, establece las listas desplegables de las pestañas UPDATE, INSERT y DELETE en (Ninguno).

Create a New ObjectDataSource Named ProductsDataSource

Figura 2: Creación de un nuevo ObjectDataSource denominado ProductsDataSource (Haz clic para ver la imagen a tamaño completo)

Configure the ObjectDataSource to Retrieve Data Using the GetProducts() Method

Figura 3: Configuración de ObjectDataSource para recuperar datos mediante el método GetProducts() (Haz clic para ver la imagen a tamaño completo)

Set the Drop-Down Lists in the UPDATE, INSERT, and DELETE Tabs to (None)

Figura 4: Establecimiento de las listas desplegables de las pestañas ACTUALIZAR, INSERTAR y ELIMINAR en (Ninguno) (Haz clic para ver la imagen a tamaño completo)

Después de completar el Asistente para configurar los orígenes de datos, Visual Studio creará automáticamente BoundColumns y CheckBoxColumn para los campos de datos relacionados con el producto. Como hicimos en el tutorial anterior, quita todos los menos los BoundFields ProductName, CategoryName, y UnitPrice, y cambia las propiedades HeaderText a Producto, Categoría y Precio. Configura el objeto de BoundField UnitPrice para que su valor tenga el formato de moneda. Además, a fin de configurar GridView para admitir la paginación, activa la casilla Habilitar paginación en tu etiqueta inteligente.

Vamos a agregar también la interfaz de usuario para eliminar los productos seleccionados. Agrega un control de botón web debajo de GridView, estableciendo su ID en DeleteSelectedProducts y su propiedad Text en Eliminar productos seleccionados. En lugar de eliminar realmente los productos de la base de datos, en este ejemplo solo mostraremos un mensaje que indica los productos que se habrían eliminado. Para dar cabida a esto, agrega un control de etiqueta web debajo del botón. Establece su id. en DeleteResults, borra su propiedad Text y establece sus propiedades Visible y EnableViewState en false.

Después de realizar estos cambios, los marcados declarativos de GridView, ObjectDataSource, Button y Label deben ser similares a los siguientes:

<p>
    <asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" EnableViewState="False">
        <Columns>
            <asp:BoundField DataField="ProductName" HeaderText="Product" 
                SortExpression="ProductName" />
            <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                ReadOnly="True" SortExpression="CategoryName" />
            <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                HeaderText="Price" HtmlEncode="False" 
                SortExpression="UnitPrice" />
        </Columns>
    </asp:GridView>
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}" 
        SelectMethod="GetProducts" TypeName="ProductsBLL">            
    </asp:ObjectDataSource>
</p>
<p>
    <asp:Button ID="DeleteSelectedProducts" runat="server" 
        Text="Delete Selected Products" />
</p>
<p>
    <asp:Label ID="DeleteResults" runat="server" EnableViewState="False" 
        Visible="False"></asp:Label>
</p>

Dedica un momento a ver la página en un explorador (observa la figura 5). En este momento deberías ver el nombre, la categoría y el precio de los diez primeros productos.

The Name, Category, and Price of the First Ten Products are Listed

Figura 5: Se observa el nombre, la categoría y el precio de los primeros diez productos (haz clic para ver la imagen a tamaño completo)

Paso 2: Agregar una columna de casillas

Dado que ASP.NET 2.0 incluye un CheckBoxField, podría pensarse que puede usarse para agregar una columna de casillas a GridView. Desafortunadamente, no es así, ya que CheckBoxField está diseñado para trabajar con un campo de datos booleano. Es decir, para usar CheckBoxField, debemos especificar el campo de datos subyacente cuyo valor se consulta para determinar si la casilla representada está activada. No se puede usar CheckBoxField para incluir simplemente una columna de casillas desactivadas.

En su lugar, debemos agregar un TemplateField y agregar un control web CheckBox a su ItemTemplate. Continúa y agrega un TemplateField a Products GridView y haz que sea el primer campo (a la izquierda). En la etiqueta inteligente GridView, haz clic en el hipervínculo Editar plantillas y, a continuación, arrastra un control web CheckBox desde el cuadro de herramientas a ItemTemplate. Establece esta propiedad ID de CheckBox en ProductSelector.

Add a CheckBox Web Control Named ProductSelector to the TemplateField s ItemTemplate

Figura 6: Agregar un control web CheckBox denominado ProductSelector al ItemTemplate de TemplateField (haz clic para ver la imagen a tamaño completo)

Con TemplateField y el control web CheckBox agregados, cada fila ahora incluye una casilla. En la figura 7 se muestra esta página, cuando se ve a través de un explorador, después de agregar TemplateField y CheckBox.

Each Product Row Now Includes a Checkbox

Figura 7: Cada fila de producto ahora incluye una casilla (haz clic para ver la imagen a tamaño completo)

Paso 3: Determinar qué casillas se activaron en postback

En este momento tenemos una columna de casillas, pero no hay forma de determinar qué casillas se activaron en postback. Sin embargo, cuando se hace clic en el botón Eliminar productos seleccionados, es necesario saber qué casillas se activaron para eliminar esos productos.

La propiedad Rows de GridView proporciona acceso a las filas de datos de GridView. Podemos iterar a través de estas filas, acceder mediante programación al control CheckBox y, a continuación, consultar su propiedad Checked para determinar si se ha seleccionado la CheckBox.

Crea un controlador de eventos para el evento Click del control del botón web DeleteSelectedProducts y agrega el código siguiente:

protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
    bool atLeastOneRowDeleted = false;
    // Iterate through the Products.Rows property
    foreach (GridViewRow row in Products.Rows)
    {
        // Access the CheckBox
        CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
        if (cb != null && cb.Checked)
        {
            // Delete row! (Well, not really...)
            atLeastOneRowDeleted = true;
            // First, get the ProductID for the selected row
            int productID = 
                Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);
            // "Delete" the row
            DeleteResults.Text += string.Format(
                "This would have deleted ProductID {0}<br />", productID);
        }
    }
    // Show the Label if at least one row was deleted...
    DeleteResults.Visible = atLeastOneRowDeleted;
}

La propiedad Rows devuelve una colección de instancias GridViewRow que maquillan las filas de datos de GridView. El bucle foreach aquí enumera esta colección. Para cada objeto GridViewRow, se accede mediante programación a las filas CheckBox utilizando row.FindControl("controlID"). Si se activa la CheckBox, se recupera el valor ProductID correspondiente de la fila de la colección DataKeys. En este ejercicio, simplemente se muestra un mensaje informativo en la etiqueta DeleteResults, aunque en una aplicación en funcionamiento, en su lugar, realizamos una llamada al método DeleteProduct(productID) de la clase ProductsBLL.

Con la adición de este controlador de eventos, al hacer clic en el botón Eliminar productos seleccionados ahora se muestran los ProductID de los productos seleccionados.

When the Delete Selected Products Button is Clicked the Selected Products ProductIDs are Listed

Figura 8: Cuando se hace clic en el botón Eliminar productos seleccionados, se muestran los ProductID de los productos seleccionados (haz clic para ver la imagen a tamaño completo)

Paso 4: Agregar Seleccionar todo y Desactivar todos los botones

Si un usuario desea eliminar todos los productos de la página actual, debe activar cada una de las diez casillas. Podemos ayudar a acelerar este proceso agregando un botón Seleccionar todo que, al hacer clic, seleccione todas las casillas de la cuadrícula. Un botón Desactivar todo sería igualmente útil.

Agrega dos controles de botón web a la página, colocándolos encima de GridView. Establece la primera ID en CheckAll y su propiedad Text en Seleccionar todo; establece la segunda ID en UncheckAll y su propiedad Text en Desactivar todo.

<asp:Button ID="CheckAll" runat="server" Text="Check All" />
 
<asp:Button ID="UncheckAll" runat="server" Text="Uncheck All" />

A continuación, crea un método en la clase de código subyacente con el nombre ToggleCheckState(checkState) que, cuando se invoca, enumera la colección Rows del control GridView Products y establece cada propiedad Checked de CheckBox en el valor del parámetro checkState pasado.

private void ToggleCheckState(bool checkState)
{
    // Iterate through the Products.Rows property
    foreach (GridViewRow row in Products.Rows)
    {
        // Access the CheckBox
        CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
        if (cb != null)
            cb.Checked = checkState;
    }
}

A continuación, crea controladores de eventos Click para los botones CheckAll y UncheckAll. En el controlador de eventos de CheckAll, simplemente llama a ToggleCheckState(true); en UncheckAll, llama a ToggleCheckState(false).

protected void CheckAll_Click(object sender, EventArgs e)
{
    ToggleCheckState(true);
}
protected void UncheckAll_Click(object sender, EventArgs e)
{
    ToggleCheckState(false);
}

Con este código, al hacer clic en el botón Seleccionar todo se produce un postback y se activan todas las casillas de GridView. Del mismo modo, al hacer clic en Desactivar todo, se anula la selección de todas las casillas. En la figura 9 se muestra la pantalla después de activar el botón Seleccionar todo.

Clicking the Check All Button Selects All Checkboxes

Figura 9: Al hacer clic en el botón Seleccionar todo se activan todas las casillas(haz clic para ver la imagen a tamaño completo)

Nota:

Al mostrar una columna de casillas, un enfoque para seleccionar o anular la selección de todas las casillas consiste en usar una casilla en la fila de encabezado. Además, para la implementación actual de Seleccionar todo y Desactivar todo se necesita un postback. Pero las casillas se pueden activar o desactivar mediante scripts del lado cliente, lo que proporciona una experiencia del usuario más rápida. Para explorar en detalle el uso de una casilla de fila de encabezado para Seleccionar todo y Desactivar todo, junto con una explicación sobre el uso de técnicas del lado cliente, consulta Selección de todas las casillas en un control GridView mediante scripts del lado cliente y una casilla Seleccionar todo.

Resumen

En los casos en los que necesites permitir que los usuarios elijan un número arbitrario de filas de un control GridView antes de continuar, agregar una columna de casillas es una opción. Como hemos visto en este tutorial, incluir una columna de casillas en GridView implica agregar una instancia de TemplateField con un control web CheckBox. Al usar un control web (frente a insertar el marcado directamente en la plantilla, como en el tutorial anterior) ASP.NET recuerda automáticamente qué casillas se han activado y cuáles no entre postback. También se puede acceder mediante programación a los controles CheckBox en el código para determinar si se ha activado una casilla determinada o para cambiar el estado activado.

En este tutorial y en el último se ha examinado la adición de una columna de selector de filas a GridView. En el siguiente tutorial verás cómo, con un poco de trabajo, puedes agregar funcionalidades de inserción a GridView.

¡Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Puedes ponerte en contacto con él en mitchell@4GuysFromRolla.com. o a través de su blog, http://ScottOnWriting.NET.