Using ASP.NET 3.5's ListView and DataPager Controls: Deleting DataBy Scott Mitchell
|A Multipart Series on ASP.NET's ListView and DataPager Controls|
This article is one in a series of articles on ASP.NET's ListView and DataPager controls, which were introduced with ASP.NET version 3.5.
The previous installments in this article series have demonstrated how to display, group, sort, and page through data using the ListView control. In addition to displaying data, the ListView control also provides support for inserting, updating, and deleting data. If the ListView uses a data source control (such as a SqlDataSource or ObjectDataSource) and that data source control is configured to support insert, updating, or deleting, then implementing such functionality in the ListView does not require writing a single line of code. Rather, adding inserting and updating support entails creating templates that define the inserting and updating user interfaces and Button controls that trigger the actual update or insert. Implementing deleting support requires simply adding a properly configured Delete button to the ItemTemplate.
This installment and the next explore how to perform inserts, updates, and deletes using the ListView control. This installment focuses on deleting and shows how to perform simple, standard deletes as well as more advanced deleting scenarios. The demos explored here (as well as the demos from previous installments) are available for download at the end of the article. Read on to learn more!
(It is assumed that the reader is familiar with how to delete data using a data source control. If this is not the case, please first read Accessing and Updating Data in ASP.NET: Deleting Data.)
An Overview of the ListView's Deleting Workflow
A ListView control that supports deleting typically includes a Delete Button with each rendered item that, when clicked, deletes the associated item. For example, the screen shot below shows a ListView control that lists the customers from the Northwind database table. Each customer item includes the customer's name and contact information along with a "Delete Customer" button.
When the "Delete Customer" Button is clicked a postback ensues and the ListView begins its deleting workflow. This workflow proceeds as follows:
- The ListView raises its
- The ListView assigns the key values for the row being deleted to the delete parameters for its associated data source control.
- The ListView calls its associated data source control's
Deletemethod, which actually performs the delete.
- The ListView raises its
From the end user's perspective, the deleting workflow unfolds like this: the user clicks the "Delete Customer" button; there's a short pause and, whoosh, the selected customer is gone!
Implementing Deleting in the ListView
Adding deleting support to the ListView requires that the ListView's underlying data source control support deleting. That means that if you are using a SqlDataSource or AccessDataSource control as the ListView's data source that the SqlDataSource (or AccessDataSource) must have a
DeleteCommandspecified. If you are using an ObjectDataSource then you will need to have specified what object method to invoke to perform the delete. For more background on configuring the data source controls to support deleting, refer to Accessing and Updating Data in ASP.NET: Deleting Data.
Recall that in order to kick off the deleting workflow there needs to be some Button control in the ItemTemplate that serves as the Delete Button. This Button can be any type
of Button control (a regular Button, a LinkButton, or an ImageButton), but it must have its
CommandName property set to "Delete". For example, the demo available
for download at the end of this article includes a ListView that displays records from the Northwind database's
Customers table. The markup for the ItemTemplate
displays the customer's
CompanyName field in an
<h3> element as well as the customer's contact person, location, and telephone number. There's
also a Button control labeled "Delete Customer" that serves as the Delete Button. Note that its
CommandName property is set to "Delete".
Along with adding a Delete Button, it's also equally important that the ListView's
DataKeyNames property be set to the column(s) that comprise the primary key.
Customers table's primary key is
CustomerID. Therefore, in order for this ListView to correctly implement deleting it is imperative that its
DataKeyNames property be set to
CustomerID, as it is in the markup above. If this property is not set then the Delete Button, when clicked, will
cause a postback but the record will not be deleted (as the data source control does not know the
CustomerID value to delete).
And... that's it! With the addition of a properly configured Delete Button and by setting the ListView's
DataKeyNames field to the primary key we now have a
ListView from which users can delete customers. That was easy.
|Debugging the Deleting Workflow|
When testing your ListView control, if you find that clicking the Delete Button does not actually delete the record, ensure that the GridView's |
If you are deleting records from a database table that have associated records in a child table and if there's a foreign key constraint in the database (as their should be)
you may get an exception if you delete a record that has children records. For example, the
If you are getting some other error or unexpected behavior and have verified that the Delete Button's
|What If I'm Not Using a Data Source Control?|
The ListView control can be bound to data via a data source control or by programmatically settings its |
Enhancing the Deleting Interface To Include a Client-Side Confirmation
The example we just examined implemented deleting but, perhaps, in a suboptimal way. Currently there's no confirmation when deleting a custom. If the user accidentally clicks the mouse while moving it over a "Delete Customer" button or if they click the incorrect "Delete Customer" button - poof - there's a postback, the customer record is deleted, and you have an angry user.
This can be mitigated by requiring the user to confirm that they want to delete the record before it is actually deleted. There are a number of ways to do this, from
taking the user to a separate page, to showing a client-side confirm dialog box, or through some custom client-side action. Perhaps the simplest way is to use a client-side
confirm function. The
confirm function displays a modal dialog box that prompts the user to click "OK" or "Cancel", and returns a true or false value, respectively. In short, we
can use the
confirm function in a manner that cancels the postback if the user clicks the "Cancel" button. We just need to have the Delete Button's client-side
onclick event handler return the value from the
The following markup shows the updated "Delete Customers" Button markup, which now has its
OnClientClick property configured to use the
With this addition a client-side popup is displayed whenever the user clicks the "Delete Customer" button. If the user clicks the "Cancel" button then the postback is cancelled and the delete does not happen; however, if the user clicks "OK" then the postback continues and the customer is deleted.
Canceling the Delete Based On Programmatic Logic
Recall that before the ListView control actually deletes the requested record it first raises its
ItemDeletingevent. This event signals that the ListView is right about to perform a delete and gives us an opportunity to cancel it, if needed. In certain scenarios there may be complex business logic that determines whether or not a particular record can be deleted. One way to enforce this business logic is to create an event handler for the
ItemDeletingevent and check to make sure that the record that is about to be deleted can, in fact, be deleted. If the record cannot be deleted then the workflow can be canceled and a message displayed to the user.
Imagine that we wanted to prevent users from deleting customers with orders. One way to prevent this would be to not cascade deletes from the foreign key constraint, but
imagine that the business rules were a bit more pervasive than that - maybe we wanted to let administrative users delete customers that have orders, but not let other users.
Whatever the case, we could put a check in the
ItemDeleting event handler and stop the delete if the customer being deleted has associated orders. The following
code snippet shows an ItemDeleting event handler that implements this business rule:
The above code is certainly not an example of best practices as it has data access code directly in the ASP.NET code-behind class, but it does illustrate how to perform
some programmatic check to determine whether or not to cancel the delete. The above code starts by determining the
CustomerID value of the customer that is
going to be deleted and does so by grabbing it from the ListView's
DataKeys collection. Next, it connects to the database and sends a query that returns the
number of records in the
Orders table for this specific customer. If that number is greater than zero then the deleting workflow is cancelled (by setting
alert function. (Alternatively, you could have displayed
such a message in a Label Web control.)
The net result is that if the user attempts to delete a customer that has orders the delete action is stopped and the user is displayed a message explaining why the could not delete that customer.
In addition to displaying data, the ListView control can also provide an interface for deleting data. Building a ListView that supports deleting involves adding a Delete Button to the ItemTemplate - namely, a Button control with its
CommandNameproperty set to "Delete" - and assigning the ListView's
DataKeyNamesproperty to the primary key name(s). When a user visiting the page clicks the Delete Button a postback ensues and the ListView's deleting workflow unfolds. Prior to deleting the record the ListView fires its
ItemDeletingevent handler. As we saw in this article, you can create an event handler for this event and cancel the workflow, if needed.
In addition to supporting deletes, the ListView also offers functionality for inserts and updates. We'll see how to insert and update data through the ListView in the next two installments.