Introduction
Inserting a new record in a database table using a GridView
has never been easy, or at least is not an out-of-the-box feature.
For this purpose, the ListView
has been introduced in which inserting a new record is an out-of-the-box feature. We’ll see how to use the ListView
in place of the GridView
to insert a new record, making the UI look just like a GridView
. This is a basic article that helps a beginner to understand the insert, edit, and delete functionalities of the ListView
control.
The ListView
control is a new data presentation control introduced in .NET 3.5 to cater to the complex business needs of displaying data. Though ListView
is provided with a huge number of properties that provide flexibility in behaviour and appearance, we are not dealing with those in this article.

On click of the Add button:

On click of the Save button with invalid entries:

Create Data Source
I am using the SqlDataSource
control to handle the insert, update, and delete functionality with inline SQL queries. You can choose to use ObjectDataSource
with DataSet
s and Stored Procedures to do the same for a better tiered architecture.
Add a ListView
In the code below, we have used four templates: ItemTemplate
, InsertItemTemplate
, EditItemTemplate
, and EmptyDataTemplate
after the mandatory LayoutTemplate
.
LayoutTemplate
LayoutTemplate
is the template for the rows parent table. Basically, this template is used to create the main (or root) layout for the control. The template will obviously have a <table>
element because this example renders data to an HTML table. However, there is no restriction. The LayoutTemplate
and ItemTemplate
should be in sync. This is because the LayoutTemplate
contains a special placeholder item that is replaced with the HTML markup generated from ItemTemplate
. So in this example, the LayoutTemplate
contains an HTML table with two child rows, one that defines the header cells, and another that is a placeholder for the databound rows. When the ListView
renders, the placeholder is replaced with what is generated from the ItemTemplate
being bound to each of the items in the data source.
<LayoutTemplate>
<table id="tblCotnacts" runat="server"
class="edit-table-listview">
<tr>
<th>Contact Type</th>
<th>Title</th>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
<th></th>
</tr>
<tr runat="server" id="itemPlaceholder"></tr>
</table>
</LayoutTemplate>
ItemTemplate
ItemTemplate
is to render all the rows by running through each of these rows to generate the read-only cells for the data item portion. This is similar to the Columns
collection of the GridView
. This is where you will use the data binding syntax to bind the values of the attributes from your data source to their corresponding UI elements.
<ItemTemplate>
<tr>
<td><%#Eval("ContactType")%></td>
<td><%#Eval("Title")%></td>
<td><%#Eval("FirstName")%></td>
<td><%#Eval("LastName")%></td>
<td><%#Eval("Phone")%></td>
<td>
<asp:ImageButton ID="imgbEdit" runat="server"
CommandName="Edit" Text="Edit"
ImageUrl="~/Images/edit_icon_mono.gif" />
<asp:ImageButton ID="imgbDelete" runat="server"
CommandName="Delete" Text="Delete"
ImageUrl="~/Images/delete_icon_mono.gif"
OnClientClick=
"return confirm('Are you sure you want to delete this contact?');"
ToolTip="Delete"/>
</td>
</tr>
</ItemTemplate>
If you observe the code, OnClientClick
has been used for the delete image button. This is to pop up a confirmation box when the user tries to delete a row.

InsertItemTemplate
InsertItemTemplate
is to have the ASP.NET controls which will be rendered when the Insert command is passed. Add controls and bind them to the data in the data source. Also, the validation controls can be added to all the input controls. Add two buttons to insert and cancel the user input. Set the causesvalidation
property of the Insert button to true
and that of the Cancel button to false
.
<InsertItemTemplate>
<tr>
<td>
<asp:DropDownList ID="ddlContactTypeInsert"
runat="server" DataSourceID="sqlDsContactType"
DataTextField="ContactType"
DataValueField="ContactTypeID"
CssClass="edit-table-input"
width="215px" AppendDataBoundItems="true">
<asp:ListItem Text="" Value=""></asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="rfvSchemeSalaryTypeInsert"
runat="server" ControlToValidate="ddlContactTypeInsert"
ErrorMessage="Missing contact type"
SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtTitleInsert"
runat="server" Text='<%# Bind("Title") %>'
width="48px"/>
</td>
<td>
<asp:TextBox ID="txtFirstNameInsert" runat="server"
Text='<%# Bind("FirstName") %>' width="78px"/>
<asp:RequiredFieldValidator ID="rfvFirstNameInsert"
runat="server" ControlToValidate="txtFirstNameInsert"
ErrorMessage="Missing first name" SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtLastNameInsert" runat="server"
Text='<%# Bind("LastName") %>' width="78px"/>
<asp:RequiredFieldValidator ID="rfvLastNameInsert"
runat="server" ControlToValidate="txtLastNameInsert"
ErrorMessage="Missing last name" SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtPhoneInsert" runat="server"
Text='<%# Bind("Phone") %>' width="113px"/>
<asp:RequiredFieldValidator ID="rfvPhoneInsert"
runat="server" ControlToValidate="txtPhoneInsert"
ErrorMessage="Missing phone number" SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:ImageButton ID="imgbInsert" runat="server"
CommandName="Insert" Text="Insert"
ImageUrl="~/Images/add_icon_mono.gif"
ValidationGroup="vgrpSaveContact"/>
<asp:ImageButton ID="imgbCancelInsert" runat="server"
CommandName="Cancel" Text="Clear"
ImageUrl="~/Images/undo_icon_mono.gif"
onclick="CancelAddNew"/>
</td>
</tr>
</InsertItemTemplate>
Implement the image button’s Click
event in the code-behind, as shown below:
Private Sub imgbNew_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgbNew.Click
lvContacts.InsertItemPosition = InsertItemPosition.FirstItem
imgbNew.Enabled = False
lvContacts.EditIndex = -1
End Sub
Use the ListView
’s ItemInserting
event to send the selected value in the dropdown to the insert parameters:
Private Sub lvContacts_ItemInserting(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.ListViewInsertEventArgs) _
Handles lvContacts.ItemInserting
e.Values("ContactTypeID") = _
TryCast(e.Item.FindControl("ddlContactTypeInsert"), DropDownList).SelectedValue
End Sub
Implement the CancelAddNew()
function in the code-behind and call it from the Listview
events ItemInserted
(to close the insert row after the insert) and ItemEditing
(to close the insert row when a row is clicked for edit):
Protected Sub CancelAddNew()
lvContacts.InsertItemPosition = InsertItemPosition.None
imgbNew.Enabled = True
End Sub
Private Sub lvContacts_ItemInserted(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.ListViewInsertedEventArgs) _
Handles lvContacts.ItemInserted
CancelAddNew()
End Sub
Private Sub lvContacts_ItemEditing(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.ListViewEditEventArgs) _
Handles lvContacts.ItemEditing
CancelAddNew()
End Sub
EditItemTemplate
EditItemTemplate
is to have the ASP.NET controls which will be rendered when the Edit command is passed. Add controls and bind them to the data in the data source. Also, validation controls can be added to all the input controls. Add two buttons to save and cancel the user input. Set the causesvalidation
property of the Save button to true
and that of the Cancel button to false
.
<EditItemTemplate>
<tr>
<td>
<asp:DropDownList ID="ddlContactTypeEdit" runat="server"
DataSourceID="sqlDsContactType" DataTextField="ContactType"
DataValueField="ContactTypeID"
CssClass="edit-table-input"
width="215px" AppendDataBoundItems="true"
SelectedValue='<%# Bind("ContactTypeID") %>'>
<asp:ListItem Text="" Value=""></asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="rfvSchemeSalaryTypeEdit"
runat="server" ControlToValidate="ddlContactTypeEdit"
ErrorMessage="Missing contact type"
SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtTitleEdit" runat="server"
Text='<%# Bind("Title") %>' width="48px"/>
</td>
<td>
<asp:TextBox ID="txtFirstNameEdit" runat="server"
Text='<%# Bind("FirstName") %>' width="78px"/>
<asp:RequiredFieldValidator ID="rfvFirstNameEdit"
runat="server" ControlToValidate="txtFirstNameEdit"
ErrorMessage="Missing first name"
SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtLastNameEdit" runat="server"
Text='<%# Bind("LastName") %>' width="78px"/>
<asp:RequiredFieldValidator ID="rfvLastNameEdit"
runat="server" ControlToValidate="txtLastNameEdit"
ErrorMessage="Missing last name" SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:TextBox ID="txtPhoneEdit" runat="server"
Text='<%# Bind("Phone") %>' width="113px"/>
<asp:RequiredFieldValidator ID="rfvPhoneEdit"
runat="server" ControlToValidate="txtPhoneEdit"
ErrorMessage="Missing phone" SetFocusOnError="true"
ValidationGroup="vgrpSaveContact" Display="None">
</asp:RequiredFieldValidator>
</td>
<td>
<asp:ImageButton ID="imgbUpdate" runat="server"
CommandName="Update" Text="Update"
ImageUrl="~/Images/save_icon_mono.gif"
CausesValidation="true"
ValidationGroup="vgrpSaveContact"/>
<asp:ImageButton ID="imgbCancel" runat="server"
CommandName="Cancel" Text="Cancel"
ImageUrl="~/Images/undo_icon_mono.gif"
CausesValidation="false"/>
</td>
</tr>
</EditItemTemplate>

EmptyDataTemplate
EmptyDataTemplate
will be fired when there is no data returned by the data source. A custom message would suffice in this case.
<EmptyDataTemplate>
<tr>
<td>
No data was returned.
</td>
</tr>
</EmptyDataTemplate>

On click of the Add button:

Validation
As we have added client side validators, we can choose to show the summary of the error messages using a ValidationSummary
control. The validation summary can either be displayed on the screen or can be popped up as a message box.
Use the ValidationGroup
attribute to all the validators to group them with the button that causes the validation. Styles can be used to generate a really nice UI for the validation summary.
<asp:ValidationSummary ID="vsumSaveContact"
runat="server" ValidationGroup="vgrpSaveContact"
EnableClientScript="true"
SkinID="valSummaryError"
DisplayMode="BulletList"
HeaderText="Please correct the below errors." />
Use the following CSS code to generate the validation summary as shown in the screenshots:
.validation-summary-errors
{
width: 300px;
border-color: Red;
border-style: solid;
border-width: 1px;
background-color:#FFFFF3;
margin: 5px 0px;
padding-top: 5px;
padding-left: 15px;
font-size: 8pt;
color: red;
}
.validation-summary-errors ul
{
list-style: disc inside;
padding:5px;
margin:2px;
}
If the summary is to be popped up, add the following attributes to the above validation summary:
ShowMessageBox="true" ShowSummary="false"

Colour Invalid Controls
Also, we have added JavaScript code to colour the invalid controls:
<script language="javascript" type="text/javascript">
function ChangeColourOfInvalidControls()
{
try
{
for (var i = 0; i < Page_Validators.length; i++)
{
var valdtr = Page_Validators[i];
var ctrl = document.getElementById(valdtr.controltovalidate);
if (ctrl != null && ctrl.style != null)
{
if (!valdtr.isvalid)
ctrl.style.backgroundColor="#F3F781";
else
ctrl.style.backgroundColor = "";
}
}
}
catch(e)
{
}
}
</script>
Register this JavaScript method in the code-behind page by using RegisterOnSubmitStatement
.
ClientScript.RegisterOnSubmitStatement(Me.Page.GetType(), _
"ChangeColourOfInvalidControls", "ChangeColourOfInvalidControls();")
The JavaScript array Page_Validators
is defined in the ASP.NET framework’s client-side scripts. If this JavaScript code generates any error, make sure to run the following command in the Visual Studio command prompt:
aspnet_regiis -c
This would install the client-side scripts for ASP.NET, such as client-side validation scripts, to the aspnet_client subdirectory of each Internet Information Services (IIS) site directory.
How to Use the Code
The complete code has been provided as a downloadable. To use this, all you need to do is to have the AdventureWorks database installed and with a little bit of tweaks.
- I am using the Person.Contacts table in this example after amending some of the columns to allow nulls.
- I have added a new column
ContactTypeID
as a foreign key to the table Person.ContactType to have a dropdown as one of the controls while inline editing. - I have used inline SQL queries in the select, update, insert, and delete commands of the data source just to make the code work. However, this is not recommended, as the best way to do is to have Stored Procedures in a multi-tier application.