Agregar y responder a los botones en un control GridView (VB)
por Scott Mitchell
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).
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
. Después, agregue estas 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
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.
Figura 3: Agregue 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. Ahora el menú de la izquierda incluye elementos para los tutoriales sobre edición, inserción y eliminación.
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
.
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.
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.
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
.
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.
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).
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.
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.
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.
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)
.
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.
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).
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)
.
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 NULL
UnitPrice
, 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 RowCommand
evento 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.
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 ButtonType
propiedad 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.
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.
Figura 20: GridView incluye el precio +10% y el precio -10% botones (haga clic para ver la imagen a tamaño completo)
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, ha trabajado 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.