Examinar los eventos relacionados con la inserción, actualización y eliminación (VB)
por Scott Mitchell
En este tutorial se examinará el uso de los eventos que se producen antes, durante y después de una operación de inserción, actualización o eliminación de un control web de datos de ASP.NET. También se verá cómo personalizar la interfaz de edición para actualizar solo un subconjunto de los campos del producto.
Introducción
Al usar las características integradas de inserción, edición o eliminación de los controles GridView, DetailsView o FormView, se realizan una variedad de pasos cuando el usuario final completa el proceso de agregar un nuevo registro o actualizar o eliminar un registro existente. Como se explicó en el tutorial anterior, cuando se edita una fila en GridView, el botón Editar se reemplaza por los botones Actualizar y Cancelar y BoundFields se convierte en Cuadros de texto. Después de que el usuario final actualice los datos y haga clic en Actualizar, se realizan los pasos siguientes en postback:
- GridView rellena los
UpdateParameters
de ObjectDataSource con los campos de identificación únicos del registro editado (mediante la propiedadDataKeyNames
) junto con los valores especificados por el usuario. - GridView invoca el método
Update()
de ObjectDataSource, que a su vez invoca el método adecuado en el objeto subyacente (ProductsDAL.UpdateProduct
, en nuestro tutorial anterior) - Los datos subyacentes, que ahora incluyen los cambios actualizados, se vuelven a enlazar a GridView.
Durante esta secuencia de pasos, se desencadenan varios eventos, lo que nos permite crear controladores de eventos para agregar lógica personalizada cuando sea necesario. Por ejemplo, antes del paso 1, se desencadena el evento RowUpdating
de GridView. En este momento, podemos cancelar la solicitud de actualización si hay algún error de validación. Cuando se invoca el método Update()
, se desencadena el evento Updating
de ObjectDataSource, lo que proporciona la oportunidad de agregar o personalizar los valores de cualquiera de los UpdateParameters
. Una vez que se haya completado la ejecución del método del objeto subyacente de ObjectDataSource, se genera el evento Updated
de ObjectDataSource. Un controlador de eventos para el evento Updated
puede inspeccionar los detalles sobre la operación de actualización, como el número de filas afectadas y si se produjo o no una excepción. Por último, después del paso 2, se desencadena el evento RowUpdated
de GridView; un controlador de eventos para este evento puede examinar información adicional sobre la operación de actualización que acaba de realizar.
En la figura 1 se muestra esta serie de eventos y pasos al actualizar GridView. El patrón de eventos de la figura 1 no es único para actualizar con GridView. La inserción, actualización o eliminación de datos de GridView, DetailsView o FormView precipita la misma secuencia de eventos previos y posteriores para el control web de datos y ObjectDataSource.
Figura 1: Se desencadena una serie de eventos previos y posteriores al actualizar datos en GridView (haga clic para ver la imagen en tamaño completo)
En este tutorial examinaremos el uso de estos eventos para ampliar las funcionalidades integradas de inserción, actualización y eliminación de los controles web de datos de ASP.NET. También se verá cómo personalizar la interfaz de edición para actualizar solo un subconjunto de los campos del producto.
Paso 1: Actualización de los campos ProductName
y UnitPrice
de un producto
En las interfaces de edición del tutorial anterior, todos los campos de producto que no eran de solo lectura tenían que incluirse. Si se quitara un campo de GridView (por ejemplo, QuantityPerUnit
) al actualizar los datos, el control web de datos no establecería el valor QuantityPerUnit
UpdateParameters
de ObjectDataSource. A continuación, ObjectDataSource pasaría un valor de Nothing
al método de capa lógica de negocios (BLL) de UpdateProduct
, que cambiaría la columna QuantityPerUnit
del registro de base de datos editado a un valor NULL
. Del mismo modo, si se elimina un campo obligatorio de la interfaz de edición, como ProductName
, la actualización fallará con la excepción "Column 'ProductName' does not allow nulls". El motivo de este comportamiento fue porque ObjectDataSource se configuró para llamar al método de la clase ProductsBLL
, UpdateProduct
, que esperaba un parámetro de entrada para cada uno de los campos de producto. Por lo tanto, la colección UpdateParameters
de ObjectDataSource contenía un parámetro para cada uno de los parámetros de entrada del método.
Si queremos proporcionar un control web de datos que permita al usuario final actualizar solo un subconjunto de campos, es necesario establecer mediante programación los valores que faltan UpdateParameters
en el controlador de eventos de Updating
de ObjectDataSource o crear y llamar a un método BLL que espera solo un subconjunto de los campos. Vamos a explorar este último enfoque.
En concreto, vamos a crear una página que muestre solo los campos ProductName
y UnitPrice
en una GridView editable. Esta interfaz de edición de GridView solo permitirá al usuario actualizar los dos campos mostrados, ProductName
y UnitPrice
. Dado que esta interfaz de edición solo proporciona un subconjunto de campos de un producto, es necesario crear un ObjectDataSource que use el método de BLL existente UpdateProduct
y que tenga los valores de campo de producto que faltan establecidos mediante programación en su controlador de eventos Updating
o necesitamos crear un nuevo método BLL que espera solo el subconjunto de campos definidos en GridView. En este tutorial, vamos a usar la última opción y crear una sobrecarga del método UpdateProduct
, una que toma solo tres parámetros de entrada: productName
, unitPrice
y productID
:
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Update, False)> _
Public Function UpdateProduct(productName As String, _
unitPrice As Nullable(Of Decimal), productID As Integer) _
As Boolean
Dim products As Northwind.ProductsDataTable = _
Adapter.GetProductByProductID(productID)
If products.Count = 0 Then
Return False
End If
Dim product As Northwind.ProductsRow = products(0)
product.ProductName = productName
If Not unitPrice.HasValue Then
product.SetUnitPriceNull()
Else
product.UnitPrice = unitPrice.Value
End If
Dim rowsAffected As Integer = Adapter.Update(product)
Return rowsAffected = 1
End Function
Al igual que el método original UpdateProduct
, esta sobrecarga comienza comprobando si hay un producto en la base de datos con el ProductID
especificado. Si no es así, devuelve False
, que indica que se produjo un error en la solicitud para actualizar la información del producto. De lo contrario, actualiza los campos ProductName
y UnitPrice
del registro de producto existente en consecuencia y confirma la actualización llamando al método Update()
de TableAdapter, pasando la instancia ProductsRow
.
Con esta adición a nuestra clase ProductsBLL
, estamos listos para crear la interfaz GridView simplificada. Abra DataModificationEvents.aspx
en la carpeta EditInsertDelete
y agregue GridView a la página. Cree un nuevo ObjectDataSource y configúrelo para usar la clase ProductsBLL
con su asignación de método Select()
a GetProducts
y su asignación de método Update()
a la sobrecarga UpdateProduct
que toma solo los parámetros de entrada productName
, unitPrice
y productID
. En la figura 2 se muestra el asistente para Crear origen de datos al asignar el método Update()
de ObjectDataSource a la nueva sobrecarga del método de la clase ProductsBLL
, UpdateProduct
.
Figura 2: Asignar el método Update()
del ObjectDataSource a la sobrecarga UpdateProduct
nueva (Haga clic para ver la imagen a tamaño completo)
Dado que nuestro ejemplo solo necesitará inicialmente la capacidad de editar datos, pero no para insertar o eliminar registros, dedique un momento a indicar explícitamente que los métodos Insert()
y Delete()
de ObjectDataSource no deben asignarse a ninguno de los métodos de la clase ProductsBLL
; para ello, vaya a las pestañas INSERT y DELETE y elija (Ninguno) en la lista desplegable.
Figura 3: Seleccionar (Ninguno) en la lista desplegable para las pestañas INSERT y DELETE (Haga clic para ver la imagen de tamaño completo)
Después de completar este asistente, active la casilla Habilitar edición en la etiqueta inteligente de GridView.
Tras la finalización del Asistente para crear origen de datos y el enlace a GridView, Visual Studio ha creado la sintaxis declarativa para ambos controles. Vaya a la vista Origen para inspeccionar el marcado declarativo de ObjectDataSource, que se muestra a continuación:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
Puesto que no hay asignaciones para los métodos Insert()
y Delete()
de ObjectDataSource, no hay ninguna sección InsertParameters
o DeleteParameters
. Además, dado que el método Update()
se asigna a la sobrecarga del método UpdateProduct
que solo acepta tres parámetros de entrada, la sección UpdateParameters
tiene solo tres instancias Parameter
.
Tenga en cuenta que la propiedad OldValuesParameterFormatString
de ObjectDataSource está establecida en original_{0}
. Visual Studio establece automáticamente esta propiedad al usar el Asistente para configurar orígenes de datos. Sin embargo, dado que nuestros métodos BLL no esperan que se pase el valor original ProductID
, quite esta asignación de propiedad por completo de la sintaxis declarativa de ObjectDataSource.
Nota:
Si simplemente borra el valor de propiedad OldValuesParameterFormatString
de la ventana Propiedades en la vista Diseño, la propiedad seguirá existiendo en la sintaxis declarativa, pero se establecerá en una cadena vacía. Por lo tanto, quite la propiedad por completo de la sintaxis declarativa o, en la ventana Propiedades, establezca el valor en el valor predeterminado, {0}
.
Aunque ObjectDataSource solo tiene UpdateParameters
para el nombre, el precio y el identificador del producto, Visual Studio ha agregado un BoundField o CheckBoxField en GridView para cada uno de los campos del producto.
Figura 4: GridView contiene un BoundField o CheckBoxField para cada uno de los campos del producto (Haga clic para ver la imagen en tamaño completo)
Cuando el usuario final edita un producto y hace clic en el botón Actualizar, GridView enumera los campos que no eran de solo lectura. A continuación, establece el valor del parámetro correspondiente en la colecciónUpdateParameters
de ObjectDataSource en el valor especificado por el usuario. Si no hay un parámetro correspondiente, GridView agrega uno a la colección. Por lo tanto, si GridView contiene BoundFields y CheckBoxFields para todos los campos del producto, ObjectDataSource terminará invocando la sobrecarga UpdateProduct
que toma todos estos parámetros, a pesar de que el marcado declarativo de ObjectDataSource especifica solo tres parámetros de entrada (vea la figura 5). Del mismo modo, si hay alguna combinación de campos de producto que no son de solo lectura en GridView que no se corresponde con los parámetros de entrada de una sobrecarga UpdateProduct
, se generará una excepción al intentar actualizar.
Figura 5: GridView agregará parámetros a la colección UpdateParameters
de ObjectDataSource (haga clic para ver la imagen en tamaño completo)
Para asegurarse de que ObjectDataSource invoca la sobrecarga UpdateProduct
que toma solo el nombre, el precio y el identificador del producto, es necesario restringir GridView para que solo tenga campos editables de ProductName
y UnitPrice
. Esto se puede lograr quitando los otros BoundFields y CheckBoxFields, estableciendo la propiedad ReadOnly
de esos otros campos en True
, o mediante alguna combinación de los dos. Para este tutorial, vamos a simplemente quitar todos los campos GridView excepto los campos ProductName
y UnitPrice
BoundFields, después de los cuales el marcado declarativo de GridView tendrá el siguiente aspecto:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="ProductName"
HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
Aunque la sobrecarga UpdateProduct
espera tres parámetros de entrada, solo tenemos dos BoundFields en GridView. Esto se debe a que el parámetro de entrada productID
es un valor de clave principal y se pasa a través del valor de la propiedad DataKeyNames
para la fila editada.
GridView, junto con la sobrecarga UpdateProduct
, permite a un usuario editar solo el nombre y el precio de un producto sin perder ninguno de los demás campos del producto.
Figura 6: La interfaz permite editar solo el nombre y el precio del producto (haga clic para ver la imagen en tamaño completo)
Nota:
Como se explicó en el tutorial anterior, es fundamental que el estado de vista de GridView esté habilitado (el comportamiento predeterminado). Si establece la propiedad EnableViewState
de GridView en false
, corre el riesgo de que los usuarios simultáneos eliminen o editen registros accidentalmente.
Mejora del formato de UnitPrice
Aunque el ejemplo de GridView que se muestra en la figura 6 funciona, el campo UnitPrice
no tiene formato alguno, lo que da lugar a una representación de precios que carece de símbolos de moneda y tiene cuatro posiciones decimales. Para aplicar un formato de moneda para las filas no editables, simplemente establezca la propiedad UnitPrice
de BoundField DataFormatString
en {0:c}
y su propiedad HtmlEncode
en False
.
Figura 7: Establecer las propiedades de UnitPrice
, DataFormatString
y HtmlEncode
adecuadamente (haga clic aquí para ver la imagen en tamaño completo)
Con este cambio, las filas no editables dan formato al precio como moneda; sin embargo, la fila editada sigue mostrando el valor sin el símbolo de moneda y con cuatro posiciones decimales.
Figura 8: Las filas no editables ahora tienen el formato de valores de moneda (haga clic para ver la imagen en tamaño completo)
Las instrucciones de formato especificadas en la propiedad DataFormatString
se pueden aplicar a la interfaz de edición estableciendo la propiedad ApplyFormatInEditMode
de BoundField en True
(el valor predeterminado es False
). Dedique un momento a establecer esta propiedad en True
.
Figura 9: establezca la propiedad UnitPrice
de Boundfield ApplyFormatInEditMode
en True
(Haga clic para ver la imagen a tamaño completo)
Con este cambio, el valor de UnitPrice
que se muestra en la fila editada también tiene el formato de moneda.
Figura 10: El valor de la fila editada UnitPrice
tiene ahora el formato de moneda (haga clic para ver la imagen en tamaño completo)
Sin embargo, la actualización de un producto con el símbolo de moneda en el cuadro de texto como 19,00 $ produce un FormatException
. Cuando GridView intenta asignar los valores proporcionados por el usuario a la colección UpdateParameters
de ObjectDataSource , no puede convertir la cadena UnitPrice
"19,00 $" en la requerida por el parámetro Decimal
(vea la figura 11). Para solucionar este problema, podemos crear un controlador de eventos para el evento RowUpdating
de GridView y hacer que analice el proporcionado por el usuario UnitPrice
como un formato de moneda Decimal
.
El evento RowUpdating
de GridView acepta como segundo parámetro un objeto de tipo GridViewUpdateEventArgs, que incluye un diccionario NewValues
como una de sus propiedades que contiene los valores proporcionados por el usuario listos para asignarse a la colección UpdateParameters
de ObjectDataSource. Podemos sobrescribir el valor existente UnitPrice
en la colección NewValues
con un valor decimal analizado mediante el formato de moneda con las siguientes líneas de código en el controlador de eventos RowUpdating
:
Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
Handles GridView1.RowUpdating
If e.NewValues("UnitPrice") IsNot Nothing Then
e.NewValues("UnitPrice") = _
Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
System.Globalization.NumberStyles.Currency)
End If
End Sub
Si el usuario ha proporcionado un valor UnitPrice
(como "19,00 $"), este valor se sobrescribe con el valor decimal calculado por Decimal.Parse, analizando el valor como una moneda. Esto analizará correctamente el decimal en caso de cualquier símbolo de moneda, comas, puntos decimales, etc., y usará la enumeración NumberStyles en el espacio de nombres System.Globalization.
En la figura 11 se muestra el problema causado por símbolos de moneda en el UnitPrice
proporcionado por el usuario, junto con cómo se puede usar el controlador de eventos RowUpdating
de GridView para analizar correctamente dicha entrada.
Figura 11: El valor de la fila editada UnitPrice
tiene ahora el formato de moneda (haga clic para ver la imagen en tamaño completo)
Paso 2: ProhibirNULL UnitPrices
Aunque la base de datos está configurada para permitir valores NULL
en la columna Products
de la tabla UnitPrice
, es posible que queramos impedir que los usuarios visiten esta página concreta especificando un valor NULL
UnitPrice
. Es decir, si un usuario no puede escribir un valor UnitPrice
al editar una fila de producto, en lugar de guardar los resultados en la base de datos, queremos mostrar un mensaje que informe al usuario de que, mediante esta página, los productos editados deben tener un precio especificado.
El objeto GridViewUpdateEventArgs
pasado al controlador de eventos de GridView RowUpdating
contiene una propiedad Cancel
que, si se establece en True
, finaliza el proceso de actualización. Vamos a extender el controlador de eventos RowUpdating
para establecer e.Cancel
y True
y mostrar un mensaje que explique por qué el valor UnitPrice
de la colección NewValues
tiene un valor de Nothing
.
Empiece agregando un control web Label a la página denominada MustProvideUnitPriceMessage
. Este control Label se mostrará si el usuario no puede especificar un valor UnitPrice
al actualizar un producto. Establezca la propiedad Label de Text
en "Debe proporcionar un precio para el producto". También he creado una nueva clase CSS en Styles.css
denominada Warning
con la siguiente definición:
.Warning
{
color: Red;
font-style: italic;
font-weight: bold;
font-size: x-large;
}
Finalmente, establezca la propiedad CssClass
de la etiqueta en Warning
. En este momento, el Diseñador debe mostrar el mensaje de advertencia en rojo, negrita, cursiva, tamaño de fuente adicional grande por encima de GridView, como se muestra en la figura 12.
Figura 12: Se ha agregado una etiqueta encima de GridView (haga clic para ver la imagen en tamaño completo)
De forma predeterminada, esta Label debe estar oculta, por lo que debe establecer su propiedad Visible
en False
en el controlador de eventos Page_Load
:
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
MustProvideUnitPriceMessage.Visible = False
End Sub
Si el usuario intenta actualizar un producto sin especificar UnitPrice
, queremos cancelar la actualización y mostrar la etiqueta de advertencia. Aumente el controlador de eventos RowUpdating
de GridView de la siguiente manera:
Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
Handles GridView1.RowUpdating
If e.NewValues("UnitPrice") IsNot Nothing Then
e.NewValues("UnitPrice") = _
Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
System.Globalization.NumberStyles.Currency)
Else
MustProvideUnitPriceMessage.Visible = True
e.Cancel = True
End If
End Sub
Si un usuario intenta guardar un producto sin especificar un precio, se cancela la actualización y se muestra un mensaje útil. Aunque la base de datos (y la lógica de negocios) permite NULL
UnitPrice
, esta página ASP.NET particular no lo hace.
Figura 13: Un usuario no puede dejar UnitPrice
en blanco (haga clic para ver la imagen en tamaño completo)
Hasta ahora hemos visto cómo usar el evento RowUpdating
de GridView para modificar mediante programación los valores de parámetro asignados a la colección UpdateParameters
de ObjectDataSource, así como cómo cancelar el proceso de actualización por completo. Estos conceptos se transfieren a los controles DetailsView y FormView y también se aplican a la inserción y eliminación.
Estas tareas también se pueden realizar en el nivel ObjectDataSource mediante controladores de eventos para sus eventos Inserting
, Updating
y Deleting
. Estos eventos se activan antes de que se invoque el método asociado del objeto subyacente y proporcionen una última oportunidad para modificar la colección de parámetros de entrada o cancelar la operación directamente. Los controladores de eventos de estos tres eventos se pasan a un objeto de tipo ObjectDataSourceMethodEventArgs que tiene dos propiedades de interés:
- Cancel, que, si se establece en
True
, cancela la operación que se está realizando. - InputParameters, que es la colección de
InsertParameters
,UpdateParameters
oDeleteParameters
, dependiendo de si el controlador de eventos es para el eventoInserting
,Updating
oDeleting
.
Para ilustrar cómo trabajar con los valores de parámetro en el nivel ObjectDataSource, vamos a incluir un DetailsView en nuestra página que permita a los usuarios agregar un nuevo producto. Este DetailsView se usará para proporcionar una interfaz para agregar rápidamente un nuevo producto a la base de datos. Para mantener una interfaz de usuario coherente al agregar un nuevo producto, vamos a permitir que el usuario solo escriba los valores de los campos ProductName
y UnitPrice
. De forma predeterminada, los valores que no se proporcionan en la interfaz de inserción de DetailsView se establecerán en un valor de base de datos NULL
. Sin embargo, podemos usar el evento ObjectDataSource Inserting
para insertar valores predeterminados diferentes, como veremos en breve.
Paso 3: Proporcionar una interfaz para agregar nuevos productos
Arrastre un control DetailsView desde el Cuadro de herramientas hasta el Diseñador situado encima de GridView, borre sus propiedades Height
y Width
y vincúlelo a ObjectDataSource ya presente en la página. Esto agregará un BoundField o CheckBoxField para cada uno de los campos del producto. Puesto que queremos usar esta vista de detalles para agregar nuevos productos, es necesario comprobar la opción Habilitar inserción desde la etiqueta inteligente; sin embargo, no hay ninguna opción de este tipo porque el método Insert()
de ObjectDataSource no está asignado a un método de la clase ProductsBLL
(recuerde que establecemos esta asignación en (None) al configurar el origen de datos, vea la figura 3).
Para configurar ObjectDataSource, seleccione el vínculo Configurar origen de datos en su etiqueta inteligente, iniciando el asistente. La primera pantalla permite cambiar el objeto subyacente al que está enlazado ObjectDataSource; déjelo establecido en ProductsBLL
. En la siguiente pantalla se enumeran las asignaciones de los métodos de ObjectDataSource al objeto subyacente. Aunque hemos indicado explícitamente que los métodos Insert()
y Delete()
no deben asignarse a ningún método, si va a las pestañas INSERT y DELETE, verá que hay una asignación allí. Esto se debe a que los métodos de ProductsBLL
, AddProduct
y DeleteProduct
, usan el atributo DataObjectMethodAttribute
para indicar que son los métodos predeterminados para Insert()
y Delete()
, respectivamente. Por lo tanto, el asistente ObjectDataSource los selecciona cada vez que ejecuta el asistente a menos que se especifique algún otro valor explícitamente.
Deje el método Insert()
que apunta al método AddProduct
, pero vuelva a establecer la lista desplegable de la pestaña DELETE en (None).
Figura 14: Establecer la lista desplegable de la pestaña INSERT en el método AddProduct
(haga clic para ver la imagen en tamaño completo)
Figura 15: Establecer la lista desplegable de la pestaña DELETE en el método (haga clic para ver la imagen en tamaño completo)
Después de realizar estos cambios, la sintaxis declarativa de ObjectDataSource se expandirá para incluir una colección InsertParameters
, como se muestra a continuación:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating"
InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
<asp:Parameter Name="categoryID" Type="Int32" />
<asp:Parameter Name="quantityPerUnit" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="unitsInStock" Type="Int16" />
<asp:Parameter Name="unitsOnOrder" Type="Int16" />
<asp:Parameter Name="reorderLevel" Type="Int16" />
<asp:Parameter Name="discontinued" Type="Boolean" />
</InsertParameters>
</asp:ObjectDataSource>
Volver a ejecutar el asistente agregó la propiedad OldValuesParameterFormatString
. Tómese un momento para borrar esta propiedad estableciendo esta propiedad en el valor predeterminado ({0}
) o quitándola por completo de la sintaxis declarativa.
Con ObjectDataSource, que proporciona funcionalidades de inserción, la etiqueta inteligente DetailsView incluirá ahora la casilla Habilitar inserción; vuelva al Diseñador y active esta opción. A continuación,pare el control DetailsView para que solo tenga dos BoundFields: ProductName
y UnitPrice
y CommandField. En este momento, la sintaxis declarativa de DetailsView debe tener el aspecto:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
<Fields>
<asp:BoundField DataField="ProductName"
HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
En la Figura 16, se muestra esta página vista desde un explorador en este punto. Como puede ver, DetailsView enumera el nombre y el precio del primer producto (Chai). Sin embargo, lo que queremos es una interfaz de inserción que proporcione un medio para que el usuario agregue rápidamente un nuevo producto a la base de datos.
Figura 16: DetailsView se representa actualmente en modo de solo lectura (haga clic para ver la imagen en tamaño completo)
Para mostrar DetailsView en su modo de inserción, es necesario establecer la propiedad DefaultMode
en Inserting
. Esto representa DetailsView en modo de inserción cuando se visita por primera vez y lo mantiene allí después de insertar un nuevo registro. Como se muestra en la figura 17, este objeto DetailsView proporciona una interfaz rápida para agregar un nuevo registro.
Figura 17: DetailsView proporciona una interfaz para agregar rápidamente un nuevo producto (haga clic para ver la imagen en tamaño completo)
Cuando el usuario escribe un nombre y un precio de producto (como "Acme Water" y 1,99, como en la figura 17) y hace clic en Insertar, se inicia un postback y comienza el flujo de trabajo de inserción, lo que culmina en un nuevo registro de producto que se agrega a la base de datos. DetailsView mantiene su interfaz de inserción y GridView se vuelve a enlazar automáticamente a su origen de datos para incluir el nuevo producto, como se muestra en la figura 18.
Figura 18: Se ha agregado el producto "Acme Water" a la base de datos
Aunque GridView no lo muestra en la figura 18, los campos de producto que carecen de la interfaz de DetailsView CategoryID
, SupplierID
, QuantityPerUnit
, etc. son valores de base de datos asignados NULL
. Puede verlo realizando los siguientes pasos:
- Vaya al Explorador de servidores en Visual Studio.
- Expanda el nodo de base de datos
NORTHWND.MDF
. - Haga clic con el botón derecho en el nodo de la base de datos
Products
. - Seleccione Mostrar datos de tabla.
Esto enumerará todos los registros de la tabla Products
. Como se muestra en la figura 19, todas las columnas del nuevo producto que no sean ProductID
, ProductName
y UnitPrice
tienen valores NULL
.
Figura 19: Los campos de producto no proporcionados en DetailsView son valores asignados NULL
(haga clic para ver la imagen en tamaño completo)
Es posible que quiera proporcionar un valor predeterminado distinto de NULL
para uno o varios de estos valores de columna, ya sea porque NULL
no es la mejor opción predeterminada o porque la propia columna de base de datos no permite NULL
. Para ello, podemos establecer mediante programación los valores de los parámetros de la colección InputParameters
de DetailsView. Esta asignación se puede realizar en el controlador de eventos del evento ItemInserting
de DetailsView o en el evento Inserting
de ObjectDataSource. Dado que ya hemos visto el uso de los eventos previos y posteriores en el nivel de control web de datos, vamos a explorar el uso de los eventos de ObjectDataSource esta vez.
Paso 4: Asignar valores a los parámetros CategoryID
y SupplierID
Para este tutorial, imaginemos que para nuestra aplicación al agregar un nuevo producto a través de esta interfaz se le debe asignar un valor CategoryID
y SupplierID
de 1. Como se mencionó anteriormente, ObjectDataSource tiene un par de eventos previos y posteriores que se activan durante el proceso de modificación de datos. Cuando se invoca su método Insert()
, ObjectDataSource genera primero su evento Inserting
, luego llama al método al que se ha asignado su método Insert()
y, por último, genera el evento Inserted
. El controlador de eventos Inserting
nos ofrece una última oportunidad para ajustar los parámetros de entrada o cancelar la operación directamente.
Nota:
En una aplicación real, es probable que quiera permitir al usuario especificar la categoría y el proveedor o elegir este valor por ellos en función de algunos criterios o lógica de negocios (en lugar de seleccionar ciegamente un identificador de 1). Independientemente, el ejemplo muestra cómo establecer mediante programación el valor de un parámetro de entrada del evento de nivel previo de ObjectDataSource.
Dedique un momento a crear un controlador de eventos para el evento Inserting
de ObjectDataSource. Observe que el segundo parámetro de entrada del controlador de eventos es un objeto de tipo ObjectDataSourceMethodEventArgs
, que tiene una propiedad para tener acceso a la colección de parámetros (InputParameters
) y una propiedad para cancelar la operación (Cancel
).
Protected Sub ObjectDataSource1_Inserting _
(sender As Object, e As ObjectDataSourceMethodEventArgs) _
Handles ObjectDataSource1.Inserting
End Sub
En este momento, la propiedad InputParameters
contiene la colección InsertParameters
de ObjectDataSource con los valores asignados desde DetailsView. Para cambiar el valor de uno de estos parámetros, simplemente use: e.InputParameters("paramName") = value
. Por lo tanto, para establecer los valores CategoryID
y SupplierID
en 1, ajuste el controlador de eventos Inserting
para que tenga un aspecto similar al siguiente:
Protected Sub ObjectDataSource1_Inserting _
(sender As Object, e As ObjectDataSourceMethodEventArgs) _
Handles ObjectDataSource1.Inserting
e.InputParameters("CategoryID") = 1
e.InputParameters("SupplierID") = 1
End Sub
Esta vez cuando se agrega un nuevo producto (como Acme Soda), las columnas CategoryID
y SupplierID
del nuevo producto se establecen en 1 (véase la figura 20).
Figura 20: Los nuevos productos ahora tienen sus valores CategoryID
y SupplierID
establecidos en 1 (haga clic para ver la imagen en tamaño completo)
Resumen
Durante el proceso de edición, inserción y eliminación, tanto el control web de datos como el ObjectDataSource continúan a través de varios eventos previos y posteriores. En este tutorial hemos examinado los eventos de nivel previo y hemos visto cómo usarlos para personalizar los parámetros de entrada o cancelar la operación de modificación de datos por completo desde el control web de datos y los eventos de ObjectDataSource. En el siguiente tutorial veremos cómo crear y usar controladores de eventos para los eventos posteriores.
¡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.
Agradecimientos especiales a
Esta serie de tutoriales contó con la revisión de muchos revisores que fueron de gran ayuda. Los revisores principales de este tutorial fueron Zack Jones y Liz Shulok. ¿Le interesaría revisar mis próximos artículos de MSDN? Si fuera así, escríbame a mitchell@4GuysFromRolla.com.
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de