Agregar una columna GridView de casillas de verificación (VB)

por Scott Mitchell

Descargar PDF

En este tutorial se explica cómo agregar una columna de botones de radio a un control GridView para proporcionar al usuario una manera más intuitiva de seleccionar varias filas del control.

Introducción

En el tutorial anterior se ha 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 se limita a elegir como máximo un elemento de la cuadrícula. Pero en ocasiones, es posible que quiera permitir al usuario elegir un número arbitrario de elementos de la cuadrícula. Por ejemplo, los clientes de correo electrónico basados en web muestran la lista de mensajes con una columna de casillas. El usuario puede seleccionar un número arbitrario de mensajes y, después, realizar una acción, como mover los correos electrónicos a otra carpeta o eliminarlos.

En este tutorial verá cómo agregar una columna de casillas y cómo determinar qué casillas se han activado durante el postback. En concreto, creará un ejemplo que imita estrechamente la interfaz de usuario de un cliente de correo electrónico basado en web. En el ejemplo se incluirá un control GridView paginado que enumera los productos de la tabla de base de datos Products con una casilla en cada fila (vea la figura 1). Al hacer clic en un botón Eliminar productos seleccionados se eliminarán esos productos seleccionados.

Each Product Row Includes a Checkbox

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

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

Antes de preocuparse de agregar una columna de casillas, primero se centrará en enumerar los productos en un control GridView que admita la paginación. Para empezar, abra la página CheckBoxField.aspx en la carpeta EnhancedGridView y arrastre un control GridView desde el Cuadro de herramientas al Diseñador, y establezca ID en Products. A continuación, elija enlazar GridView a un nuevo objeto ObjectDataSource denominado ProductsDataSource. Configure ObjectDataSource para usar la clase ProductsBLL y llame al método GetProducts() para devolver los datos. Como este control GridView será de solo lectura, establezca las listas desplegables de las pestañas UPDATE, INSERT y DELETE en (None).

Create a New ObjectDataSource Named ProductsDataSource

Figura 2: Creación de una instancia de ObjectDataSource con el nombre ProductsDataSource (Haga 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() (Haga 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 UPDATE, INSERT y DELETE en (None) (Haga clic para ver la imagen a tamaño completo)

Después de completar el Asistente para configurar orígenes de datos, Visual Studio creará automáticamente instancias de BoundColumn y CheckBoxColumn para los campos de datos relacionados con el producto. Como en el tutorial anterior, quite todo menos las instancias ProductName, CategoryName y UnitPrice de BoundField, y cambie las propiedades HeaderText a Product, Category y Price. Configure la instancia UnitPrice de BoundField para que su valor tenga el formato de moneda. Además, a fin de configurar GridView para admitir la paginación, active la casilla Habilitar paginación en su etiqueta inteligente.

Agregará también la interfaz de usuario para eliminar los productos seleccionados. Agregue un control web Button debajo de GridView, y establezca 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 se mostrará un mensaje que indica los productos que se habrían eliminado. Para dar cabida a esto, agregue un control web Label debajo del botón. Establezca su id. en DeleteResults, borre su propiedad Text y establezca sus propiedades Visible y EnableViewState en False.

Después de realizar estos cambios, el marcado declarativo de GridView, ObjectDataSource, Button y Label debe ser similar al siguiente:

<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>

Dedique un momento a ver la página en un explorador (vea la figura 5). En este momento debería 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 muestran el nombre, la categoría y el precio de los primeros diez productos (Haga clic para ver la imagen a tamaño completo)

Paso 2: Adición de una columna de casillas

Como en ASP.NET 2.0 se incluye un control CheckBoxField, podría pensar que se podría usar para agregar una columna de casillas a GridView. Desafortunadamente, no es el caso, ya que CheckBoxField está diseñado para trabajar con un campo de datos booleano. Es decir, para usar CheckBoxField, se debe 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, tendrá que agregar una instancia de TemplateField y agregar un control web CheckBox a su valor ItemTemplate. Continúe y agregue una instancia de TemplateField al control GridView Products y conviértalo en el primer campo (en el extremo izquierdo). Desde la etiqueta inteligente de GridView, haga clic en el vínculo Editar plantillas y, después, arrastre un control Web CheckBox desde el Cuadro de herramientas a ItemTemplate. Establezca esta propiedad IDde CheckBox en ProductSelector.

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

Figura 6: Adición de un control web CheckBox con el nombre ProductSelector al valor ItemTemplate de TemplateField (Haga clic para ver la imagen a tamaño completo)

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

Each Product Row Now Includes a Checkbox

Figura 7: La fila de cada producto incluye una casilla (Haga clic para ver la imagen a tamaño completo)

Paso 3: Determinación de qué casillas se han activado durante el postback

En este momento hay una columna de casillas, pero no hay manera de determinar qué casillas se han activado durante el postback. Pero cuando se hace clic en el botón Eliminar productos seleccionados, es necesario saber qué casillas se han activado para eliminar esos productos.

La propiedad Rows de GridView proporciona acceso a las filas de datos de GridView. Se puede iterar por estas filas, acceder mediante programación al control CheckBox y, después, consultar su propiedad Checked para determinar si se ha seleccionado el control CheckBox.

Cree un controlador de eventos para el evento Click del control web Button DeleteSelectedProducts y agregue el código siguiente:

Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
    Handles DeleteSelectedProducts.Click
    
    Dim atLeastOneRowDeleted As Boolean = False
    ' Iterate through the Products.Rows property
    For Each row As GridViewRow In Products.Rows
        ' Access the CheckBox
        Dim cb As CheckBox = row.FindControl("ProductSelector")
        If cb IsNot Nothing AndAlso cb.Checked Then
            ' Delete row! (Well, not really...)
            atLeastOneRowDeleted = True
            ' First, get the ProductID for the selected row
            Dim productID As Integer = _
                Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
            ' "Delete" the row
            DeleteResults.Text &= String.Format( _
                "This would have deleted ProductID {0}<br />", productID)
            '... To actually delete the product, use ...
            ' Dim productAPI As New ProductsBLL
            ' productAPI.DeleteProduct(productID)
            '............................................
        End If
    Next
    ' Show the Label if at least one row was deleted...
    DeleteResults.Visible = atLeastOneRowDeleted
End Sub

La propiedad Rows devuelve una colección de instancias de GridViewRow que componen las filas datos de GridView. El bucle For Each enumera esta colección. Para cada objeto GridViewRow, se accede mediante programación a la fila de CheckBox por medio de row.FindControl("controlID"). Si se activa CheckBox, se recupera de la colección DataKeys el valor ProductID correspondiente de la fila. En este ejercicio, simplemente se muestra un mensaje informativo en la etiqueta DeleteResults, aunque en una aplicación en funcionamiento, en su lugar se realizaría 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 valores 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 valores ProductID de los productos seleccionados (Haga clic para ver la imagen a tamaño completo)

Paso 4: Adición de los botones Activar todo y Desactivar todo

Si un usuario quiere eliminar todos los productos de la página actual, debe activar cada una de las diez casillas. Se puede acelerar este proceso si se agrega un botón Activar todo que, al pulsarlo, seleccione todas las casillas de la cuadrícula. Un botón Desactivar todo sería igualmente útil.

Agregue dos controles web Button a la página, encima de GridView. Establezca el valor ID del primero en CheckAll y su propiedad Text en Activar todo; establezca el valor ID del segundo 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, cree 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 Sub ToggleCheckState(ByVal checkState As Boolean)
    ' Iterate through the Products.Rows property
    For Each row As GridViewRow In Products.Rows
        ' Access the CheckBox
        Dim cb As CheckBox = row.FindControl("ProductSelector")
        If cb IsNot Nothing Then
            cb.Checked = checkState
        End If
    Next
End Sub

A continuación, cree controladores de eventos Click para los botones CheckAll y UncheckAll. En el controlador de eventos de CheckAll, simplemente llame a ToggleCheckState(True); en UncheckAll, llame a ToggleCheckState(False).

Protected Sub CheckAll_Click(sender As Object, e As EventArgs) _
    Handles CheckAll.Click
    
    ToggleCheckState(True)
End Sub
Protected Sub UncheckAll_Click(sender As Object, e As EventArgs) _
    Handles UncheckAll.Click
    
    ToggleCheckState(False)
End Sub

Con este código, al hacer clic en el botón Activar 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 Activar todo.

Clicking the Check All Button Selects All Checkboxes

Figura 9: Al hacer clic en el botón Activar todo se activan todas las casillas(Haga 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 Activar 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 Activar todo y Desactivar todo, junto con una explicación sobre el uso de técnicas del lado cliente, vea Activación de todas las casillas en un control GridView mediante scripts del lado cliente y una casilla Activar todo.

Resumen

En los casos en los que necesite 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 ha 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 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 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á cómo, con un poco de trabajo, puede agregar funcionalidades de inserción a GridView.

¡Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP y ASP.NET, y fundador de 4GuysFromRolla.com, trabaja 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. Puede ponerse en contacto con él a través de mitchell@4GuysFromRolla.com. o de su blog, que se puede encontrar en http://ScottOnWriting.NET.