Agregar y responder a los botones en un control GridView (VB)

por Scott Mitchell

Descargar PDF

En este tutorial, veremos cómo agregar botones personalizados, tanto a una plantilla como a los campos de un control GridView o DetailsView. En concreto, vamos a crear una interfaz con un control FormView que permita al usuario pasar páginas para ver los proveedores.

Introducción

Aunque muchos escenarios de informes implican acceso de solo lectura a los datos del informe, no es raro que los informes incluyan la capacidad de realizar acciones basadas en los datos mostrados. Normalmente, esto implica agregar un control web Botones, LinkButton o ImageButton con cada registro mostrado en el informe que, cuando se haga clic en él, genere un postback e invoque código del lado servidor. La edición y eliminación de los datos en una modalidad de registro por registro es el ejemplo más común. De hecho, como vimos a partir del tutorial Información general sobre la inserción, actualización y eliminación de datos, la edición y la eliminación son tan comunes que los controles GridView, DetailsView y FormView puedan admitir dicha funcionalidad sin necesidad de escribir una sola línea de código.

Además de los botones Editar y Eliminar, los controles GridView, DetailsView y FormView también pueden incluir Botones, LinkButtons o ImageButtons que, cuando se haga clic en ellos, realicen alguna lógica personalizada del lado servidor. En este tutorial, veremos cómo agregar botones personalizados, tanto a una plantilla como a los campos de un control GridView o DetailsView. En concreto, vamos a crear una interfaz con un control FormView que permita al usuario pasar páginas para ver los proveedores. Para un proveedor determinado, el control FormView mostrará información sobre el proveedor junto con un control web Botones que, si se hace clic en él, marcará todos sus productos asociados como descontinuados. Además, GridView enumera esos productos ofrecidos por el proveedor seleccionado, con cada fila que contiene botones de aumentar precio y precio de descuento que, si se hace clic en ellos, aumentan o reducen el UnitPrice del producto en un 10 % (véase la Figura 1).

Both the FormView and GridView Contain Buttons That Perform Custom Actions

Figura 1: FormView y GridView contienen botones que realizan acciones personalizadas (haga clic para ver la imagen a tamaño completo)

Paso 1: agregar las páginas web de tutoriales sobre botones

Antes de ver cómo agregar botones personalizados, primero tomemos un momento para crear las páginas ASP.NET en nuestro proyecto de sitio web, que necesitaremos para este tutorial. Empiece agregando una nueva carpeta denominada CustomButtons. Luego, agregue las siguientes dos páginas ASP.NET a esa carpeta, asegurándose de asociar cada página a la página maestra Site.master:

  • Default.aspx
  • CustomButtons.aspx

Add the ASP.NET Pages for the Custom Buttons-Related Tutorials

Figura 2: agregar las páginas ASP.NET para los tutoriales sobre botones personalizados

Igual que en las otras carpetas, Default.aspx en la carpeta CustomButtons enumerará los tutoriales en su sección. Recuerde que el control de usuario SectionLevelTutorialListing.ascx proporciona esta funcionalidad. Por lo tanto, agregue este control de usuario a Default.aspx arrastrándolo desde el Explorador de soluciones a la vista Diseño de la página.

Add the SectionLevelTutorialListing.ascx User Control to Default.aspx

Figura 3: agregar el control de usuario SectionLevelTutorialListing.ascx a Default.aspx (haga clic aquí para ver la imagen a tamaño completo)

Por último, agregue las siguientes páginas como entradas al archivo Web.sitemap. En concreto, agregue el siguiente marcado después de la paginación y ordenación <siteMapNode>:

<siteMapNode
    title="Adding Custom Buttons"
    description="Samples of Reports that Include Buttons for Performing
                  Server-Side Actions"
    url="~/CustomButtons/Default.aspx">
    <siteMapNode
        title="Using ButtonFields and Buttons in Templates"
        description="Examines how to add custom Buttons, LinkButtons,
                      or ImageButtons as ButtonFields or within templates."
        url="~/CustomButtons/CustomButtons.aspx" />
</siteMapNode>

Después de actualizar Web.sitemap, dedique un momento a ver el sitio web de tutoriales desde un explorador. El menú de la izquierda ahora incluye elementos para la edición, inserción y eliminación de tutoriales.

The Site Map Now Includes the Entry for the Custom Buttons Tutorial

Figura 4: el mapa del sitio ahora incluye la entrada para el tutorial sobre botones personalizados

Paso 2: agregar un control FormView que enumere los proveedores

Para empezar a trabajar con este tutorial, agregue el control FormView que enumera los proveedores. Como se describe en la Introducción, este control FormView permitirá al usuario pasar páginas para ver los proveedores, mostrando los productos proporcionados por el proveedor en un control GridView. Además, este control FormView incluirá un botón que, cuando se haga clic en él, marcará todos los productos del proveedor como descontinuados. Antes de preocuparnos por agregar el botón personalizado al control FormView, primero vamos a crear el control FormView para que muestre la información del proveedor.

Para empezar, abra la página CustomButtons.aspx en la carpeta CustomButtons. Agregue un control FormView a la página arrastrándolo desde el cuadro de herramientas al Diseñador y establezca su propiedad ID en Suppliers. En la etiqueta inteligente de GridView, elija crear un objeto ObjectDataSource denominado SuppliersDataSource.

Create a New ObjectDataSource Named SuppliersDataSource

Figura 5: crear un nuevo ObjectDataSource denominado SuppliersDataSource (haga clic para ver la imagen a tamaño completo)

Configure este nuevo ObjectDataSource de modo que realice consultas desde el método GetSuppliers() de la clase SuppliersBLL (véase la figura 6). Puesto que el control FormView no proporciona una interfaz para actualizar la información del proveedor, seleccione la opción (None) en la lista desplegable de la pestaña UPDATE.

Configure the Data Source to use the SuppliersBLL Class s GetSuppliers() Method

Figura 6: configurar ObjectDataSource para usar el método GetSuppliers() de la clase SuppliersBLL (haga clic para ver la imagen a tamaño completo)

Después de configurar ObjectDataSource, Visual Studio generará un InsertItemTemplate, EditItemTemplate y ItemTemplate para el control FormView. Quite el InsertItemTemplate y EditItemTemplate y modifique el ItemTemplate para que muestre solo el nombre de empresa y el número de teléfono del proveedor. Por último, active la compatibilidad con la paginación para el control FormView activando la casilla Habilitar paginación desde su etiqueta inteligente (o estableciendo su propiedad AllowPaging en True). Después de estos cambios, el marcado declarativo de la página debe tener un aspecto similar al siguiente:

<asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
    DataSourceID="SuppliersDataSource" EnableViewState="False" AllowPaging="True">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CompanyName" runat="server"
                Text='<%# Bind("CompanyName") %>' />
        </h3>
        <b>Phone:</b>
        <asp:Label ID="PhoneLabel" runat="server" Text='<%# Bind("Phone") %>' />
    </ItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

En la figura 7, se muestra la página CustomButtons.aspx cuando se visualiza en un explorador.

The FormView Lists the CompanyName and Phone Fields from the Currently Selected Supplier

Figura 7: FormView enumera los campos CompanyName y Phone del proveedor seleccionado actualmente (haga clic para ver la imagen a tamaño completo)

Paso 3: agregar un control GridView que enumere los productos del proveedor seleccionado

Antes de agregar el botón Descontinuar todos los productos a la plantilla de FormView, primero vamos a agregar un control GridView debajo de FormView que enumere los productos proporcionados por el proveedor seleccionado. Para ello, agregue un control GridView a la página, establezca su propiedad ID en SuppliersProducts y cree un nuevo ObjectDataSource denominado SuppliersProductsDataSource.

Create a New ObjectDataSource Named SuppliersProductsDataSource

Figura 8: Crear un nuevo ObjectDataSource denominado SuppliersProductsDataSource (haga clic para ver la imagen a tamaño completo)

Configure este ObjectDataSource para usar el método GetProductsBySupplierID(supplierID) de la clase ProductsBLL (véase la figura 9). Aunque GridView permitirá que se ajuste el precio de un producto, no usará la edición integrada ni eliminará características de GridView. Por lo tanto, podemos establecer la lista desplegable en (None) para las pestaña ACTUALIZAR, INSERTAR y ELIMINAR de ObjectDataSource.

Configure the Data Source to use the ProductsBLL Class s GetProductsBySupplierID(supplierID) Method

Figura 9: configurar ObjectDataSource para usar el método GetProductsBySupplierID(supplierID) de la clase ProductsBLL (haga clic para ver la imagen a tamaño completo)

Dado que el método GetProductsBySupplierID(supplierID) acepta un parámetro de entrada, el asistente ObjectDataSource nos pide el origen de este valor de parámetro. Para pasar el valor SupplierID desde FormView, establezca la lista desplegable Origen de parámetros en Control y la lista desplegable ControlID en Suppliers (el id. del FormView creado en el paso 2).

Indicate that the supplierID Parameter Should Come from the Suppliers FormView Control

Figura 10: indicar que el parámetro supplierID debe provenir del control Suppliers de FormView (haga clic para ver la imagen a tamaño completo)

Después de completar el asistente ObjectDataSource, el control GridView contendrá un BoundField o CheckBoxField para cada uno de los campos de datos del producto. Vamos a recortar esto para mostrar solo los BoundFields ProductName y UnitPrice junto con el CheckBoxField Discontinued; además, vamos a dar formato al BoundField UnitPrice de modo que su texto tenga el formato de moneda. El marcado declarativo del control GridView y del ObjectDataSource de SuppliersProductsDataSource debe tener un aspecto similar al siguiente:

<asp:GridView ID="SuppliersProducts" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
    EnableViewState="False" runat="server">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:C}"
            HtmlEncode="False" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:ControlParameter ControlID="Suppliers" Name="supplierID"
            PropertyName="SelectedValue" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

En este momento, nuestro tutorial muestra un informe maestros y de detalles, lo que permite al usuario elegir un proveedor del FormView en la parte superior para ver los productos ofrecidos por ese proveedor a través de GridView en la parte inferior. En la figura 11, se muestra una captura de pantalla de esta página al seleccionar el proveedor Tokyo Traders en el FormView.

The Selected Supplier s Products are Displayed in the GridView

Figura 11: se muestran los productos del proveedor seleccionado en GridView (haga clic para ver la imagen a tamaño completo)

Paso 4: crear métodos DAL y BLL para descontinuar todos los productos de un proveedor

Antes de poder agregar un botón a FormView que, cuando se haga clic él, descontinúe todos los productos del proveedor, primero necesitamos agregar un método a DAL y BLL que realice esta acción. En concreto, este método se denominará DiscontinueAllProductsForSupplier(supplierID). Cuando se hace clic en el botón de FormView, invocaremos este método en la capa lógica de negocios (BLL), pasando el SupplierID del proveedor seleccionado; la BLL llamará al método capa de acceso a datos (DAL) correspondiente, que emitirá una instrucción UPDATE a la base de datos que descontinúa los productos del proveedor especificado.

Como hemos hecho en nuestros tutoriales anteriores, vamos a usar un enfoque de abajo hacia arriba, comenzando por crear el método DAL, luego el método BLL y, por último, vamos a implementar la funcionalidad en la página ASP.NET. Abra el conjunto de datos con tipo Northwind.xsd en la carpeta App_Code/DAL y agregue un nuevo método a ProductsTableAdapter (haga clic con el botón derecho en ProductsTableAdapter y elija Agregar consulta). Al hacerlo, aparecerá el Asistente para configuración de consultas de TableAdapter, que nos guiará por el proceso de agregar el nuevo método. Empiece por indicar que el método DAL usará una instrucción SQL ad hoc.

Create the DAL Method Using an Ad-Hoc SQL Statement

Figura 12: crear el método mediante una instrucción SQL ad hoc (haga clic para ver la imagen a tamaño completo)

Luego, el asistente nos pide información sobre el tipo de consulta que se va a crear. Dado que el método DiscontinueAllProductsForSupplier(supplierID) tendrá que actualizar la tabla Products de la base de datos, estableciendo el campo Discontinued en 1 para todos los productos ofrecidos por el supplierID especificado, es necesario crear una consulta que actualice los datos.

Choose the UPDATE Query Type

Figura 13: elija el tipo de consulta ACTUALIZAR (haga clic para ver la imagen a tamaño completo)

La siguiente pantalla del asistente proporciona la instrucción UPDATE existente de TableAdapter, que actualiza cada uno de los campos definidos en la DataTable Products. Reemplace este texto de consulta por la siguiente instrucción:

UPDATE [Products] SET
   Discontinued = 1
WHERE SupplierID = @SupplierID

Después de escribir esta consulta y hacer clic en Siguiente, la última pantalla del asistente solicita el nombre del nuevo método; use DiscontinueAllProductsForSupplier. Para finalizar el asistente, haga clic en el botón Finalizar. Al volver al Diseñador del conjuntos de datos, debería ver un nuevo método en el ProductsTableAdapter denominado DiscontinueAllProductsForSupplier(@SupplierID).

Name the New DAL Method DiscontinueAllProductsForSupplier

Figura 14: asignar el nombre al nuevo método DAL DiscontinueAllProductsForSupplier (haga clic para ver la imagen de tamaño completo)

Con el método DiscontinueAllProductsForSupplier(supplierID) creado en la capa de acceso a datos, la siguiente tarea consiste en crear el método DiscontinueAllProductsForSupplier(supplierID) en la capa lógica de negocios. Para ello, abra el archivo de clase ProductsBLL y agregue lo siguiente:

Public Function DiscontinueAllProductsForSupplier(supplierID As Integer) As Integer
    Return Adapter.DiscontinueAllProductsForSupplier(supplierID)
End Function

Este método simplemente llama al método DiscontinueAllProductsForSupplier(supplierID) en la DAL y pasa el valor del parámetro supplierID proporcionado. Si hubiera alguna regla de negocios que solo permitiera que los productos de un proveedor se descontinúen en determinadas circunstancias, esas normas se deben aplicar aquí, en la BLL.

Nota:

A diferencia de las sobrecargas de UpdateProduct de la clase ProductsBLL, la firma del método DiscontinueAllProductsForSupplier(supplierID) no incluye el atributo DataObjectMethodAttribute (<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>). Esto excluye el método DiscontinueAllProductsForSupplier(supplierID) de la lista desplegable en la pestaña ACTUALIZAR del Asistente para configurar orígenes de datos de ObjectDataSource. He omitido este atributo porque llamaremos al método DiscontinueAllProductsForSupplier(supplierID) directamente desde un controlador de eventos en la página de ASP.NET.

Paso 5: agregar un botón Descontinuar todos los productos a FormView

Con el método DiscontinueAllProductsForSupplier(supplierID) en las BLL y DAL completado, el paso final para agregar la capacidad de descontinuar todos los productos para el proveedor seleccionado es agregar un control web de botón al control al ItemTemplate de FormView. Vamos a agregar este tipo de botón debajo del número de teléfono del proveedor con el texto del botón, Descontinuar todos los productos y un valor de propiedad de ID de DiscontinueAllProductsForSupplier. Para agregar este control web de botón a través del Diseñador, haga clic en el vínculo Editar plantillas de la etiqueta inteligente de FormView (vea la figura 15) o directamente en la sintaxis declarativa.

Add a Discontinue All Products Button Web Control to the FormView s ItemTemplate

Figura 15: agregar un control web de botón Descontinuar todos los productos a ItemTemplate de FormView (haga clic para ver la imagen a tamaño completo)

Cuando un usuario que visita la página hace clic en el botón, se activa un postback y se desencadena el evento ItemCommand de FormView. Para ejecutar código personalizado en respuesta a este botón en el que se hace clic, podemos crear un controlador de eventos para este evento. Sin embargo, hay que comprende que el evento ItemCommand se activa cada vez que se hace clic en cualquier control web Botón, LinkButton o ImageButton en FormView. Esto significa que cuando el usuario se mueve de una página a otra en FormView, el evento ItemCommand se activa; lo mismo cuando el usuario hace clic en Nuevo, Editar o Eliminar en un FormView que admite la inserción, actualización o eliminación.

Dado que ItemCommand se activa independientemente del botón en el que se hace clic, en el controlador de eventos, necesitamos una manera de determinar si se hizo clic en el botón Descontinuar todos los productos o en otro botón. Para ello, podemos establecer la propiedad CommandName del control web de botón en algún valor de identificación. Cuando se hace clic en el botón, este valor CommandName se pasa al controlador de eventos ItemCommand, lo que nos permite determinar si se hizo clic en el botón Descontinuar todos los productos. Establezca la propiedad CommandName del botón Descontinuar todos los productos en DiscontinueProducts.

Por último, vamos a usar un cuadro de diálogo de confirmación del lado cliente para asegurarnos de que el usuario realmente quiere descontinuar los productos del proveedor seleccionado. Como vimos en el tutorial Agregar confirmación del cliente al eliminar, esto se puede lograr con un poco de JavaScript. En concreto, establezca la propiedad OnClientClick del control web de botón en return confirm('This will mark _all_ of this supplier\'s products as discontinued. Are you certain you want to do this?');.

Después de realizar estos cambios, la sintaxis declarativa de FormView debe ser similar a la siguiente:

<asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
    DataSourceID="SuppliersDataSource" EnableViewState="False"
    AllowPaging="True">
    <ItemTemplate>
        <h3><asp:Label ID="CompanyName" runat="server"
            Text='<%# Bind("CompanyName") %>'></asp:Label></h3>
        <b>Phone:</b>
        <asp:Label ID="PhoneLabel" runat="server" Text='<%# Bind("Phone") %>' />
        <br />
        <asp:Button ID="DiscontinueAllProductsForSupplier" runat="server"
            CommandName="DiscontinueProducts" Text="Discontinue All Products"
            OnClientClick="return confirm('This will mark _all_ of this supplier\'s
                products as discontinued. Are you certain you want to do this?');" />
    </ItemTemplate>
</asp:FormView>

Después, cree un controlador de eventos para el evento ItemCommand de FormView. En este controlador de eventos, es necesario determinar primero si se hizo clic en el botón Descontinuar todos los productos. Si es así, debemos crear una instancia de la clase ProductsBLL e invocar su método DiscontinueAllProductsForSupplier(supplierID), pasando el SupplierID del FormView seleccionado:

Protected Sub Suppliers_ItemCommand(sender As Object, e As FormViewCommandEventArgs) _
    Handles Suppliers.ItemCommand
    If e.CommandName.CompareTo("DiscontinueProducts") = 0 Then
        ' The "Discontinue All Products" Button was clicked.
        ' Invoke the ProductsBLL.DiscontinueAllProductsForSupplier(supplierID) method
        ' First, get the SupplierID selected in the FormView
        Dim supplierID As Integer = CType(Suppliers.SelectedValue, Integer)
        ' Next, create an instance of the ProductsBLL class
        Dim productInfo As New ProductsBLL()
        ' Finally, invoke the DiscontinueAllProductsForSupplier(supplierID) method
        productInfo.DiscontinueAllProductsForSupplier(supplierID)
    End If
End Sub

Tenga en cuenta que se puede acceder al SupplierID del proveedor seleccionado actual en FormView mediante la propiedad SelectedValue de FormView. La propiedad SelectedValue devuelve el primer valor de clave de datos del registro que se muestra en FormView. La propiedad DataKeyNames de FormView, que indica los campos de datos de los que se extraen los valores de clave de datos, se ha establecido en SupplierID automáticamente en Visual Studio al enlazar ObjectDataSource a FormView en el paso 2.

Con el controlador de eventos ItemCommand ya creado, tómese un momento para probar la página. Vaya al proveedor Cooperativa de Quesos “Las Cabras” (es el quinto proveedor en el FormView para mí). Este proveedor ofrece dos productos, Queso Cabrales y Queso Manchego La Pastora, ambos no descontinuados.

Imagine que la Cooperativa de Quesos “Las Cabras” ha dejado de operar y, por lo tanto, sus productos deben descontinuarse. Haga clic en el botón Descontinuar todos los productos. Se mostrará el cuadro de diálogo de confirmar del lado cliente (véase la Figura 16).

Cooperativa de Quesos Las Cabras Supplies Two Active Products

Figura 16: Cooperativa de Quesos Las Cabras ofrece dos productos activos (haga clic para ver la imagen a tamaño completo)

Si hace clic en OK en el cuadro de diálogo de confirmación del lado cliente, el envío del formulario continuará, lo que generará un postback en el que se activará el evento ItemCommand de FormView. El controlador de eventos que hemos creado se ejecutará, invocando el método DiscontinueAllProductsForSupplier(supplierID) y descontinuando los productos Queso Cabrales y Queso Manchego La Pastora.

Si ha deshabilitado el estado de vista de GridView, GridView se está rebotando en el almacén de datos subyacente en cada postback y, por lo tanto, se actualizará inmediatamente para reflejar que estos dos productos ahora están descontinuados (consulte la figura 17). Sin embargo, si no ha deshabilitado el estado de visualización en el GridView, deberá volver a enlazar manualmente los datos al GridView después de realizar este cambio. Para ello, simplemente realice una llamada al método DataBind() de GridView inmediatamente después de invocar el método DiscontinueAllProductsForSupplier(supplierID).

After Clicking the Discontinue All Products Button, the Supplier s Products are Updated Accordingly

Figura 17: después de hacer clic en el botón Discontinue All Products, los productos del proveedor se actualizan en consecuencia (haga clic para ver la imagen de tamaño completo)

Paso 6: crear una sobrecarga UpdateProduct en la capa lógica de negocios para ajustar el precio de un producto

Al igual que con el botón Descontinuar todos los productos en el FormView, para agregar botones a fin de aumentar y reducir el precio de un producto en el GridView, primero necesitamos agregar los métodos de capa de acceso a datos y capa de lógica de negocios adecuados. Puesto que ya tenemos un método que actualiza una sola fila de producto en la DAL, podemos proporcionar esta funcionalidad mediante la creación de una nueva sobrecarga para el método UpdateProduct en la BLL.

Nuestras sobrecargas pasadas de UpdateProduct han incluido algunas combinaciones de campos de producto como valores de entrada escalares y, luego, se han actualizado solo esos campos para el producto especificado. Para esta sobrecarga, vamos desviarnos ligeramente de este estándar y, en su lugar, vamos a pasar el ProductID del producto y el porcentaje según el que se ajustará el UnitPrice (en lugar de pasar el nuevo UnitPrice ajustado). Este enfoque simplificará el código que necesitamos escribir en la clase de código subyacente de la página ASP.NET, ya que no tenemos que molestarnos en determinar el UnitPrice del producto actual.

A continuación, se muestra la sobrecarga UpdateProduct para este tutorial:

Public Function UpdateProduct _
    (unitPriceAdjustmentPercentage As Decimal, productID As Integer) As Boolean
    Dim products As Northwind.ProductsDataTable = Adapter.GetProductByProductID(productID)
    If products.Count = 0 Then
        ' no matching record found, return false
        Return False
    End If
    Dim product As Northwind.ProductsRow = products(0)
    ' Adjust the UnitPrice by the specified percentage (if it's not NULL)
    If Not product.IsUnitPriceNull() Then
        product.UnitPrice *= unitPriceAdjustmentPercentage
    End If
    ' Update the product record
    Dim rowsAffected As Integer = Adapter.Update(product)
    ' Return true if precisely one row was updated, otherwise false
    Return rowsAffected = 1
End Function

Esta sobrecarga recupera información sobre el producto especificado a través del método GetProductByProductID(productID) de la DAL. Luego, comprueba si el UnitPrice del producto tiene asignado un valor de base de datos NULL. Si es así, el precio se deja sin cambios. Sin embargo, si no hay ningún valor UnitPrice de NULL, el método actualiza el UnitPrice del producto según el porcentaje especificado (unitPriceAdjustmentPercent).

Paso 7: agregar los botones Aumentar y Disminuir al GridView

El GridView (y el DetailsView) se componen de una colección de campos. Además de BoundFields, CheckBoxFields y TemplateFields, ASP.NET incluye ButtonField, que, como su nombre implica, se representa como una columna con un Botón, LinkButton o ImageButton para cada fila. Al igual que formView, al hacer clic en cualquier botón dentro de los botones de paginación GridView, botones Editar o Eliminar, ordenar botones, etc. provoca un postback y genera el RowCommandevento GridView.

ButtonField tiene una propiedad CommandName que asigna el valor especificado a cada una de sus propiedades Botones CommandName. Al igual que con FormView, el controlador de eventos RowCommand usa el valor CommandName para determinar qué botón se hizo clic.

Vamos a agregar dos nuevos ButtonFields a GridView, uno con un texto de botón Precio +10 % y el otro con el texto Precio -10 %. Para agregar estos ButtonFields, haga clic en el vínculo Editar columnas de la etiqueta inteligente GridView, seleccione el tipo de campo ButtonField de la lista de la parte superior izquierda y haga clic en el botón Agregar.

Add Two ButtonFields to the GridView

Figura 18: agregar dos ButtonFields a GridView

Mueva los dos ButtonFields para que aparezcan como los dos primeros campos GridView. A continuación, establezca las propiedades Text de estos dos ButtonFields en Precio +10% y Precio -10% y las propiedades CommandName en IncreasePrice y DecreasePrice, respectivamente. De forma predeterminada, un ButtonField representa su columna de botones como LinkButtons. Sin embargo, esto se puede cambiar a través de la ButtonTypepropiedad ButtonField. Vamos a tener estos dos ButtonFields representados como botones de inserción normales; por lo tanto, establezca la propiedad ButtonType en Button. En la figura 19 se muestra el cuadro de diálogo Campos después de realizar estos cambios; a continuación se muestra el marcado declarativo de GridView.

Configure the ButtonFields Text, CommandName, and ButtonType Properties

Figura 19: configurar las propiedades ButtonFields Text, CommandName y ButtonType

<asp:GridView ID="SuppliersProducts" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
    EnableViewState="False">
    <Columns>
        <asp:ButtonField ButtonType="Button" CommandName="IncreasePrice"
            Text="Price +10%" />
        <asp:ButtonField ButtonType="Button" CommandName="DecreasePrice"
            Text="Price -10%" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:C}"
            HtmlEncode="False" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>

Con estos ButtonFields creados, el último paso consiste en crear un controlador de eventos para el evento RowCommand de GridView. Este controlador de eventos, si se desencadena porque se hizo clic en los botones Precio +10 % o Precio -10 %, debe determinar el ProductID para la fila cuyo botón se hizo clic y, a continuación, invocar el método UpdateProduct de la clase ProductsBLL, pasando el ajuste de porcentaje adecuado UnitPrice junto con ProductID. Este código realiza las siguientes tareas:

Protected Sub SuppliersProducts_RowCommand _
    (sender As Object, e As GridViewCommandEventArgs) _
        Handles SuppliersProducts.RowCommand
    If e.CommandName.CompareTo("IncreasePrice") = 0 OrElse _
       e.CommandName.CompareTo("DecreasePrice") = 0 Then
        ' The Increase Price or Decrease Price Button has been clicked
        ' Determine the ID of the product whose price was adjusted
        Dim productID As Integer = Convert.ToInt32( _
            SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)
        ' Determine how much to adjust the price
        Dim percentageAdjust As Decimal
        If e.CommandName.CompareTo("IncreasePrice") = 0 Then
            percentageAdjust = 1.1
        Else
            percentageAdjust = 0.9
        End If
        ' Adjust the price
        Dim productInfo As New ProductsBLL()
        productInfo.UpdateProduct(percentageAdjust, productID)
    End If
End Sub

Para determinar el ProductID para la fila cuyo botón Precio +10% o Precio -10% se hizo clic, necesitamos consultar la colección DataKeys de GridView. Esta colección contiene los valores de los campos especificados en la propiedad DataKeyNames para cada fila GridView. Dado que Visual Studio estableció la propiedad DataKeyNames de GridView en ProductID al enlazar ObjectDataSource a GridView, DataKeys(rowIndex).Value proporciona el ProductID para el rowIndex especificado.

El ButtonField pasa automáticamente el rowIndex de la fila cuyo botón fue pulsado a través del parámetro e.CommandArgument. Por lo tanto, para determinar el ProductID para la fila cuyo botón Precio +10% o Precio -10% se hizo clic, usamos: Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value).

Al igual que con el botón Interrumpir todos los productos, si ha deshabilitado el estado de vista de GridView, GridView se está rebotando en el almacén de datos subyacente en cada postback y, por tanto, se actualizará inmediatamente para reflejar un cambio de precio que se produce al hacer clic en cualquiera de los botones. Sin embargo, si no ha deshabilitado el estado de visualización en el GridView, deberá volver a enlazar manualmente los datos al GridView después de realizar este cambio. Para ello, simplemente realice una llamada al método DataBind() de GridView inmediatamente después de invocar el método UpdateProduct.

En la figura 20 se muestra la página al ver los productos proporcionados por Grandma Kelly's Homestead. En la figura 21 se muestran los resultados después de que se haya hecho clic en el botón Precio +10% dos veces para la Grandma's Boysenberry Spread y el botón Precio -10% una vez para Northwoods Cranberry Sauce.

The GridView Includes Price +10% and Price -10% Buttons

Figura 20: GridView incluye el precio +10% y el precio -10% botones (haga clic para ver la imagen a tamaño completo)

The Prices for the First and Third Product Have Been Updated via the Price +10% and Price -10% Buttons

Figura 21: los precios del primer y el tercer producto se han actualizado a través de los botones Precio +10% y Precio -10% (Haga clic para ver la imagen a tamaño completo)

Nota:

GridView (y DetailsView) también pueden tener Botones, LinkButtons o ImageButtons agregados a sus TemplateFields. Al igual que con BoundField, estos Botones, cuando se hace clic, inducirán un postback, lo que generará el evento RowCommand de GridView. Sin embargo, al agregar botones en templateField, el botón de CommandArgument no se establece automáticamente en el índice de la fila, ya que se usa ButtonFields. Si necesita determinar el índice de fila del botón en el que se hizo clic en el controlador de eventos RowCommand, deberá establecer manualmente la propiedad CommandArgument Botones en su sintaxis declarativa dentro de TemplateField, usando código como:
<asp:Button runat="server" ... CommandArgument='<%# CType(Container, GridViewRow).RowIndex %>' />.

Resumen

Los controles GridView, DetailsView y FormView pueden incluir Botones, LinkButtons o ImageButtons. Estos botones, cuando se hace clic, provocan un postback y generan el evento ItemCommand en los controles FormView y DetailsView y el evento RowCommand en GridView. Estos controles web de datos tienen funcionalidad integrada para controlar acciones comunes relacionadas con comandos, como eliminar o editar registros. Sin embargo, también podemos usar botones que, cuando se hace clic, responden con la ejecución de nuestro propio código personalizado.

Para ello, es necesario crear un controlador de eventos para el evento ItemCommand o RowCommand. En este controlador de eventos, primero comprobamos el valor CommandName entrante para determinar en qué botón se hizo clic y, a continuación, realizar la acción personalizada adecuada. En este tutorial hemos visto cómo usar botones y ButtonFields para interrumpir todos los productos de un proveedor especificado o para aumentar o reducir el precio de un producto determinado en un 10 %.

¡Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, lleva trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, instructor y escritor. Su libro más reciente es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Puede ponerse en contacto con él en mitchell@4GuysFromRolla.com. o a través de su blog, http://ScottOnWriting.NET.