Data Entry with a FormView
Sometimes it is not necessary to perform full-featured editing; it's just a matter of performing
data entry. This need crops up routinely on Web sites with forms to fill out for taking orders,
conducting surveys, registering for memberships, and other common types of information gathering.
In these cases, the need is simply to display a data entry form and to write collected information
to a database. Although any of the information editing controls can perform this task, the FormView
is particularly attractive because of its flexibility in formatting the data collection instrument.
The following FormView demonstrates a data entry form. Here it is used to perform data entry to
add records to the Books table of the BooksDB.mdb
database; however, it can be adapted for use in any type of data entry situation.
Note that making actual changes to the BooksDB.mdb database is not
permitted in these tutorials; however, all other functions work as expected.
Figure 9-23. Data entry with a FormView.
Setting the DefaultMode
A FormView normally operates in three modes. Its <ItemTemplate>
configures the form for display of a data source record, its <EditItemTemplate>
displays edit boxes for making changes to the record, and its
<InsertItemTemplate> displays blank edit boxes for adding a new record. For presenting
a data entry form, however, only the <InsertItemTemplate> is of
interest. At the same time, there is only need to display "Insert" and "Cancel" buttons to activate
data entry.
Code for the FormView to display a data entry form is shown below along with its AccessDataSource
controls.
<style type="text/css">
table#AddTable th {font-size:11pt; text-align:left; vertical-align:top;
background-color:#E0E0E0}
table#AddTable td {font-size:11pt; vertical-align:top}
table#AddTable th {font-size:11pt; text-align:left; vertical-align:top;
background-color:#E0E0E0}
.buttons {background-color:#E0E0E0}
.errmsg {width:180px}
</style>
<asp:AccessDataSource id="BookSource" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
InsertCommand="INSERT INTO Books (BookID, BookType, BookTitle,
BookAuthor,BookDescription, BookPrice, BookQty,
BookSale) VALUES (@BookID, @BookType, @BookTitle,
@BookAuthor, @BookDescription, @BookPrice, @BookQty,
@BookSale)"
/>
<asp:AccessDataSource id="TypeSource" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT DISTINCT BookType FROM Books ORDER BY BookType"/>
<h3>Book Entry</h3>
<asp:FormView id="DEFormView" DataSourceID="BookSource" Runat="Server"
DefaultMode="Insert"
OnItemInserting="Validate_Insert_Data">
<InsertItemTemplate>
<table id="AddTable" border="0" cellpadding="1">
<tr>
<th>ID</th>
<td><asp:TextBox id="BookID" Text='<%# Bind("BookID") %>' Runat="Server"
Width="70" MaxLength="6"/></td>
<td class="errmsg">
<asp:Label id="ERRBookID" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Type</th>
<td><asp:DropDownList id="BookType" Runat="Server"
DataSourceID="TypeSource"
DataTextField="BookType"
DataValueField="BookType"
SelectedValue='<%# Bind("BookType") %>'/></td>
<td></td>
</tr>
<tr>
<th>Title</th>
<td><asp:TextBox id="BookTitle" Runat="Server"
Text='<%# Bind("BookTitle") %>'
Width="300" MaxLength="50"/></td>
<td class="errmsg">
<asp:Label id="ERRBookTitle" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Author</th>
<td><asp:TextBox id="BookAuthor" Runat="Server"
Text='<%# Bind("BookAuthor") %>'
Width="300" MaxLength="50"/></td>
<td class="errmsg">
<asp:Label id="ERRBookAuthor" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Description</th>
<td><asp:TextBox id="BookDescription" Runat="Server"
Text='<%# Bind("BookDescription") %>'
TextMode="MultiLine" Rows="5" Width="300px"
Font-Name="Arial" Font-Size="9pt"/></td>
<td class="errmsg">
<asp:Label id="ERRBookDescription" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Price</th>
<td><asp:TextBox id="BookPrice" Runat="Server"
Text='<%# Bind("BookPrice") %>'
Width="60" MaxLength="6" Style="text-align:right"/></td>
<td class="errmsg">
<asp:Label id="ERRBookPrice" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Quantity</th>
<td><asp:TextBox id="BookQty" Runat="Server"
Text='<%# Bind("BookQty") %>'
Width="60" MaxLength="2" Style="text-align:right"/></td>
<td class="errmsg">
<asp:Label id="ERRBookQty" ForeColor="#FF0000" Runat="Server"
EnableViewState="False"/></td>
</tr>
<tr>
<th>Sale</th>
<td><asp:CheckBox id="BookSale" Checked='<%# Bind("BookSale") %>'
Runat="Server"/></td>
</tr>
<tr>
<th></th>
<td class="buttons">
<asp:Button id="InsertButton" CommandName="Insert" Text="Insert"
Font-Size="9pt" Width="50" Runat="Server"/>
<asp:Button id="CancelButton" CommandName="Cancel" Text="Cancel"
Font-Size="9pt" Width="50" Runat="Server"/>
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
<asp:Label id="AddMSG" ForeColor="#FF0000" EnableViewState="False"
Runat="Server"/>
Listing 9-33. Coding a FormView for data entry.
Normally, a FormView opens in ReadOnly mode to display the first of the selected records from its
AccessDataSource in its <ItemTemplate>. In this case, however, there is no
set of selected records for display since the AccessDataSource does not have a
SelectCommand property. Neither does the FormView have an
<ItemTemplate>. With no data to bind to the form and with no way to display it, the
FormView simply would not appear on the page.
The need is to open the FormView in its Insert mode rather than its default "ReadOnly" mode.
This is accomplished by adding the DefaultMode="Insert" property to
the FormView as is done in the above example. Now, the form is opened as a set of input areas
as it would appear when clicking the standard FormView's "New" button and switching to insert mode.
Also, if necessary, you can open the FormView in Edit mode by setting its
DefaultMode="Edit" property, assuming you also have a SelectCommand
statement that retrieves an initial record.
Since the FormView opens in Insert mode, it is necessary to provide appropriate command buttons
to activate the form. Buttons with CommandName="Insert" and
CommandName="Cancel" are provided. An OnItemInserting event handler
calls a subprogram when the ItemInserting event occur to validate input values.
Notice that all input areas have <#% Bind(field) %>
binding expressions to link with the parameters of the InsertCommand.
These expressions do not bind "forward" from a data source to an insert box for display; they bind
"backwards" from the input areas to the INSERT statement for inserting
entered values.
Each input area has an associated message display Label to its right. These separate message
areas make it possible to display separate data entry errors. Also, there is a message Label
at the end of the FormView to report success or failure in adding a record to the database.
Scripting the FormView
Most of the scripting effort is to validate entered data to ensure its correctness and
reasonableness prior to writing the record to the database. Much of the code is adapted from
previous scripts.
<%@ Import Namespace="System.Data.OleDb" %>
<SCRIPT Runat="Server">
Sub Validate_Insert_Data (Src As Object, Args As FormViewInsertEventArgs)
Dim MSGLabel As Label
If Args.Values("BookID") = "" Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookID")
MSGLabel.Text = "• Missing BookID"
End If
Dim DBConnection As OleDbConnection
Dim DBCommand As OleDbCommand
Dim SQLString As String
DBConnection = New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath("../Databases/BooksDB.mdb"))
DBConnection.Open()
SQLString = "SELECT Count(*) FROM Books " & _
"WHERE BookID = '" & Args.Values("BookID") & "'"
DBCommand = New OleDbCommand(SQLString, DBConnection)
If DBCommand.ExecuteScalar() <> 0 Then
MSGLabel = DEFormView.FindControl("ERRBookID")
MSGLabel.Text = "• Duplicate BookID"
Args.Cancel = True
End If
DBConnection.Close()
If Args.Values("BookTitle") = "" Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookTitle")
MSGLabel.Text = "• Missing title"
End If
If Args.Values("BookAuthor") = "" Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookAuthor")
MSGLabel.Text = "• Missing author"
End If
If Args.Values("BookDescription") = "" Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookDescription")
MSGLabel.Text = "• Missing description"
End If
If Not IsNumeric(Args.Values("BookPrice")) Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookPrice")
MSGLabel.Text = "• Price not numeric"
Else
If Args.Values("BookPrice") < 0 _
OR Args.Values("BookPrice") > 200 Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookPrice")
MSGLabel.Text = "• Price out of range"
End If
End If
If Not IsNumeric(Args.Values("BookQty")) Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookQty")
MSGLabel.Text = "• Qty not numeric"
Else
If Args.Values("BookQty") < 0 Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookQty")
MSGLabel.Text = "• Qty out of range"
End If
End If
If Args.Cancel = True Then
AddMSG.Text = "Record " & Args.Values("BookID") & " Not Added"
Else
AddMSG.Text = "Record " & Args.Values("BookID") & " Added"
End If
End Sub
</SCRIPT>
Listing 9-34. Scripting a FormView used for data validation.
When the "Insert" button is clicked and an Inserting event occurs, the
Validate_Insert_Data subprogram is called. This subprogram validates submitted data for
all except the DropDownList and CheckBox fields. A typical check is shown below for the
BookID TextBox.
Dim MSGLabel As Label
If Args.Values("BookID") = "" Then
Args.Cancel = True
MSGLabel = DEFormView.FindControl("ERRBookID")
MSGLabel.Text = "-- Missing BookID"
End If
...
Listing 9-35. Scripting a FormView to validate a data entry field.
In this case, the BookID textbox is tested for an entry. If it is
missing, then the inserting event is cancelled (Args.Cancel="True")
and an error message is displayed in the associated Label.
Since message labels appear inside the FormView, they must be "found" prior to their use. Here,
the Label with id="ERRBookID" is located with
DEFormView.FindControl("ERRBookID") and assigned to a script-generated Label
(MSGLabel) for assignment of the "Missing BookID"
message.
Since there are six different message areas, there is the need to find all six and to assign
them to Labels. It is not necessary, however, to create six different scripted Labels. All
FindControl() methods can assign to the same shared control as is
done here by declaring MSGLabel as the shared global Label.
It should be meantioned that the FormView's FindControl() method cannot
be applied in this same format to GridView or DetailsView controls. The reason is that the FormView
has only one "row" to search for a control. These other controls have multiple rows whose index
numbers must be used to identify on which row to look for a control. These
FindControl() differences are pointed out in later tutorials.
A test of made of the BookID entry to avoid writing a duplicate
record to the database. This test involves connecting to the database and returning a Count(*) of the number of records with a BookID
matching the entered value. If the count is 0, then there are no
matching records and the new record can be added. If the count is not 0,
then a matching record was found and a duplicate-record message is displayed.
DBConnection = New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath("../Databases/BooksDB.mdb"))
DBConnection.Open()
SQLString = "SELECT Count(*) FROM Books " & _
"WHERE BookID = '" & Args.Values("BookID") & "'"
DBCommand = New OleDbCommand(SQLString, DBConnection)
If DBCommand.ExecuteScalar() <> 0 Then
MSGLabel = DEFormView.FindControl("ERRBookID")
MSGLabel.Text = "• Duplicate BookID"
Args.Cancel = True
End If
DBConnection.Close()
Listing 9-36. Testing for a duplicate BookID.
Whether or not the entered information is added to the database, a message is displayed
indicating the results. This message area is located outside the FormView, so it can be
referenced directly to display the message.
If Args.Cancel = True Then
AddMSG.Text = "Record " & Args.Values("BookID") & " Not Added"
Else
AddMSG.Text = "Record " & Args.Values("BookID") & " Added"
End If
Listing 9-37. Displaying a record-addition results message.