Using ASP.NET 3.5's ListView and DataPager Controls: Inserting DataBy Scott Mitchell
The ListView control is similar to the GridView control in many ways: both display a set of records, both support built-in sorting, paging, editing, and deleting functionality with minimal effort. The ListView differs from the GridView in two key ways:
- Rather than using fields, the ListView is rendered via templates, which offers the page developer much finer control over the emitted markup, and
- The ListView supports built-in inserting support
In a nutshell, inserting data from the ListView requires two steps: defining the inserting interface via the
and specifying where the inserting interface should go via the
InsertItemPosition property. Much like with
editing data from within the ListView, the
InsertItemTemplate can contain two-way databinding statements when using a data source control to get the inputs entered
by the user from the ListView's inserting interface into the parameters of the data source control. And like with the editing and
deleting workflows, you can programmatically examine and modify the user's submitted data before inserting the data, cancelling the
operation altogether if needed.
This article walks through the steps for creating a ListView that allows users to insert records. It also shows how to optionally cancel the inserting workflow based on programmatic logic. Read on to learn more!
(It is assumed that the reader is familiar with how to insert data using a data source control. If this is not the case, please first read Accessing and Updating Data in ASP.NET: Inserting Data.)
An Overview of the ListView's Inserting Workflow
A ListView control that supports inserting includes some sort of inserting interface. This interface includes input Web controls to collect the data to add a new record - TextBoxes, CheckBoxes, DropDownLists, and so forth - along with Insert and Cancel buttons. Clicking the Insert button adds a new record using the user-supplied values; the Cancel button, when clicked, resets the inserting interface to its initial state by clearing out the TextBoxes, returning the DropDownLists to the first item, and so on.
The screen shot below shows a ListView control that has an inserting interface defined and has it displayed as the first item. In
other words, it appears before any other content defined in the
ItemTemplate. The inserting interface may be displayed
as the first or last item; it's location is configured via the
InsertItemPosition property. The Insert button
in the screen shot below is implemented as an ImageButton and displays a green plus icon.
Clicking the Insert button causes a postback and starts the ListView down the inserting workflow path:
- The ListView raises its
- The ListView assigns the values supplied in the inserting interface to the insert parameters for its associated data source control.
- The ListView calls its associated data source control's
Insertmethod, which actually performs the insert.
- The ListView raises its
- The ListView rebinds to its data source.
From the end user's perspective, the inserting workflow unfolds like this: the enters the values for the new record into the TextBoxes, DropDownLists, and other input Web controls in the inserting interface. Next, she clicks the Insert button; there's a short pause and the inserting interface is returned to its initial state and the just-added record is displayed in the ListView.
Implementing the Inserting Interface (
InsertItemTemplate) and Setting the
Adding inserting support to the ListView requires that the ListView's underlying data source control support inserting. 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 an
InsertCommandspecified. If you are using an ObjectDataSource then you will need to have specified what object method to invoke to perform the insert. For more background on configuring the data source controls to support inserting, refer to Accessing and Updating Data in ASP.NET: Inserting Data.
Recall that implementing inserting involves two key steps: defining the inserting interface via the
and specifying where the inserting interface should be placed via the
InsertItemPosition property. The
InsertItemTemplate must contain the input Web controls to collect the user's input. The demo available for download
at the end of this article shows how to insert new records into the Northwind database's
Products table, allowing the
user to supply the values for the new product's name, supplier, category, and price. These four values are stored in the
The markup for the inserting interface (shown below) includes two TextBoxes - one for the
ProductName field and one
UnitPrice - and two DropDownLists - one for
SupplierID and one for
There's also two ImageButton controls that are the Insert and Cancel buttons. The Insert and Cancel buttons can be implemented as
Button, LinkButton, or ImageButton controls, but they must have their
CommandName properties set to "Insert" and
Finally, the markup below also includes the assignment of the
InsertItemPosition to the value "FirstItem". This property
can be set to "FirstItem", "LastItem", or "None". Setting it to "FirstItem" displays the inserting interface before any of the
ListView's rendered items.
As the markup above illustrates, the
InsertItemTemplate can also include validation Web controls. The
txtProductName TextBox has a RequiredFieldValidator associated with it, as the
ProductName field is required,
txtUnitPrice TextBox has a CompareValidator to ensure that a non-negative, currency-formatted value is
|Validation With a ListView That Supports Inserting and Editing|
The ListView used in this demo supports inserting, but does not support editing. However, it is possible to create a ListView that
provides both inserting and editing functionality. If you create such a ListView and add validation controls to both the inserting
and editing interfaces you may find that you cannot update a record until you "satisfy" the validators in the inserting interface.
This is because by default ASP.NET checks all validation controls on the page when submitting. Long story short, even though
the user is not inserting a record the Update button from the editing interface triggers the inserting-related validation controls
The good news is that it's easy to partition the validation controls into separate validation groups - one for inserting and one for editing - which alleviates this issue. For more information on ASP.NET's validation controls and separating them into distinct groups, refer to Dissecting the Validation Controls in ASP.NET.
Two-Way Databinding in the Inserting Interface
As discussed in the Editing Data installment we explored how to use ASP.NET's two-way databinding syntax to get the values entered by the user into the editing interface into the data source control's update parameters. In short, you use the
Bindstatement to both assign a value into a Web control property when the editing interface is displayed and to take the value of that property and send it back out to the update parameters when the Update button is clicked. For example, with a TextBox you'd use the
Bindstatement on the
Textproperty like so:
The inserting interface shown above includes
Bind statements on the
TextBox controls. When the user clicks the Insert button the ListView takes the values entered into these TextBoxes and puts them
in the corresponding insert parameters in its data source control. You may have noticed that there are no
on the DropDownLists. Usually you'd have a
Bind statement on the DropDownList's
However, if you are using ASP.NET version 3.5 and add such a
Bind statement you'll get the following error when visiting
the page in a browser:
System.InvalidOperationException: Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
This behavior is a bug in the ListView control in ASP.NET version 3.5. According to Microsoft it will be fixed in ASP.NET version 4.0. In the meantime to work around it you need to do the following:
- Remove any
Bindstatements from the DropDownList controls in the
- Create an event handler for the ListView's
ItemInsertingevent, which fires after the user has clicked the Insert button but before the insert command is sent to the data source control
- Programmatically reference the DropDownList control(s) in the
InsertItemTemplateusing the syntax:
- Set the appropriate value(s) in the
e.Valuescollection to the
SelectedValueproperty of the DropDownList control(s)
ItemInsertingevent handler follows. Note that if you are using C# you would reference the
Valuescollection items using square brackets instead of parentheses, like:
e.Values["CategoryID"] = ....
With this code in place our ListView is complete! The user can visit the page, enter values into the TextBoxes and DropDownLists in
the inserting interface, and click the Insert button to add a new record to the
The screen shots below show the end user's experience as she adds a new product to the database. The first screen shot shows the inserting interface after the user has entered in the new product's information. The second screen shot shows the ListView after the user has clicked the Insert button. Note that the inserting interface is returned to its initial state and the ListView displays the just-added record.
Short-Circuiting the Inserting Workflow
In some scenarios you may want to cancel the inserting workflow based on the user's input or some other type of programmatic logic. Perhaps the range of values that a user can enter for the new product's price depend on the supplier or category, or maybe there are certain business rules that disallow certain supplier/category pairings.
Whatever the rationale may be, you have an opportunity to examine the values to be inserted before the insert is committed via
handler. The demo available at the end of this article includes such an event handler that
checks to see if the
ProductName value entered by the user contains
more than three words. If such a lengthy product name is found then the update is canceled and the user is shown a message explaining
The code for the
ItemInserting event handler is straightforward. It pulls the value entered into the
field via the
It then splits on spaces (" "). If there are more than two spaces in the product name then, presumably, there are more than three
words, so the update is canceled by setting
e.Cancel to True and a message is displayed via the
DisplayAlert method, which is defined in a custom
If the check passes then the values from the DropDownLists are assigned to the appropriate parameters
Values collection and a message is displayed informing the user that their product was added.
The following screen shot shows the client-side messagebox that is displayed when the user attempts to add a new product with a name that's more than three words (such as "Aniseed Syrup Is Good!")
The ListView control provides inserting, updating, and deleting functionality. As we saw in this installment, adding inserting capabilities to the ListView is relatively straightforward: create an inserting interface and set the ListView's
InsertItemPositionproperty to either "FirstItem" or "LastItem", depending on where you want the inserting interface to appear. Keep in mind that in the inserting interface you cannot use two-way databinding to retrieve data from a DropDownList control; instead, you have to programmatically reference the DropDownLists and assign their
SelectedValueproperties to the appropriate values in the
Valuescollection. This assignment can be performed from the ListView's
ItemInsertingevent handler. And that's it! The data source control handles the actual insert logic.