A Repeater can be used for database editing, although additional scripting is required beyond that needed for a GridView, DetailsView, or FormView. Also, a Repeater does not incorporate many of the built-in editing features of these other controls. Still, it is not too difficult to adapt this information display control to an editing control as shown in the following example of editing the Books table of the BooksDB.mdb database. What becomes problematic in using a Repeater for editing is the lack of a paging mechanism. This absence limits the Repeater to editing databases of relatively modest sizes.
Note that making actual changes to the BooksDB.mdb database is not permitted in these tutorials; however, all other functions work as expected.
The Repeater Form
The Repeater displays all records and fields in the Books table within a set of data input areas. The data items can be edited directly in the fields and the "Update" button for that record is clicked to rewrite the information to the database. Also associated with each record is a "Delete" button for removing the record from the database. The top row of the Repeater displays blank input areas and an "Insert" button for entering data and creating a new record. Data validation is not performed in this example.
Two AccessDataSource controls are needed. One populates the Repeater with records from the database. The second supplies book types for the drop-down lists. Code for all controls is shown below.
<asp:AccessDataSource id="BookSource" Runat="Server" DataFile="../Databases/BooksDB.mdb" SelectCommand = "SELECT * FROM Books ORDER BY BookID"/> <asp:AccessDataSource id="TypeSource" Runat="Server" DataFile="../Databases/BooksDB.mdb" SelectCommand = "SELECT DISTINCT BookType FROM Books ORDER BY BookType"/> <h3>Book Edit</h3> <asp:Label id="EditMessage" Text=" " ForeColor="#FF0000" Runat="Server"/><br/> <asp:Repeater id="RepeaterEdit" Runat="Server" DataSourceID="BookSource" OnItemCommand="Edit_Record"> <HeaderTemplate> <table id="RepeaterTable" border="1" style="border-collapse:collapse"> <tr style="background-color:#E0E0E0"> <th>ID</th> <th>Type</th> <th>Title</th> <th>Author</th> <th>Description</th> <th>Price</th> <th>Qty</th> <th>Sale</th> <th>Edit</th> </tr> <tr> <td><asp:TextBox id="BookID" Runat="Server" Font-Size="8pt" Width="45px"/></td> <td><asp:DropDownList id="BookType" Runat="Server" DataSourceID="TypeSource" DataTextField="BookType" DataValueField="BookType" Font-Size="8pt"/></td> <td><asp:TextBox id="BookTitle" Runat="Server" Font-Size="8pt" Width="80px"/></td> <td><asp:TextBox id="BookAuthor" Runat="Server" Font-Size="8pt" Width="90px"/></td> <td><asp:TextBox id="BookDescription" Runat="Server" TextMode="MultiLine" Font-Name="Arial" Font-Size="7pt" Width="150" Rows="2"/></td> <td><asp:TextBox id="BookPrice" Runat="Server" Font-Size="8pt" Width="50px" Style="text-align:right"/></td> <td><asp:TextBox id="BookQty" Runat="Server" Font-Size="8pt" Width="25px" Style="text-align:right"/></td> <td><asp:CheckBox id="BookSale" Runat="Server"/></td> <td nowrap> <asp:Button Text="Insert" CommandName="Insert" Runat="Server" Font-Size="7pt" Width="45"/></td> </tr> <tr> <td colspan="9" style="border-bottom:solid 1 black"></td> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td><asp:TextBox id="BookID" ReadOnly="True" Runat="Server" Text='<%# Eval("BookID") %>' Font-Size="8pt" Width="45px"/></td> <td><asp:DropDownList id="BookType" Runat="Server" DataSourceID="TypeSource" DataTextField="BookType" DataValueField="BookType" SelectedValue='<%# Eval("BookType") %>' Font-Size="8pt"/></td> <td><asp:TextBox id="BookTitle" Runat="Server" Text='<%# Eval("BookTitle") %>' Font-Size="8pt" Width="80px"/></td> <td><asp:TextBox id="BookAuthor" Runat="Server" Text='<%# Eval("BookAuthor") %>' Font-Size="8pt" Width="90px"/></td> <td><asp:TextBox id="BookDescription" Runat="Server" Text='<%# Eval("BookDescription") %>' TextMode="MultiLine" Font-Name="Arial" Font-Size="7pt" Width="150" Rows="2"/></td> <td><asp:TextBox id="BookPrice" Runat="Server" Text='<%# Eval("BookPrice") %>' Font-Size="8pt" Width="50px" Style="text-align:right"/></td> <td><asp:TextBox id="BookQty" Runat="Server" Text='<%# Eval("BookQty") %>' Font-Size="8pt" Width="25px" Style="text-align:right"/></td> <td><asp:CheckBox id="BookSale" Runat="Server" Checked='<%# Eval("BookSale") %>'/></td> <td nowrap> <asp:Button Text="Update" CommandName="Update" Runat="Server" Font-Size="7pt" Width="45"/> <asp:Button Text="Delete" CommandName="Delete" Runat="Server" Font-Size="7pt" Width="45"/></td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater>
You should note that data binding expressions are in the format <%# Eval("field") %>. The Eval() method is used rather than the Bind() method needed when working with a GridView, DetailsView, and FormView.
Locating Repeater Controls
A Repeater responds to user events such as clicks on its enclosed buttons by including an OnItemCommand event handler. In the current example, this event handler calls subprogram Edit_Record when any of the "Insert," "Update," or "Delete" buttons is clicked. The subprogram called by an OnItemCommand event handler must have the argument RepeaterCommandEventArgs. Also, the buttons must include CommandName properties to identify themselves to the called subprogram.
Rows in a Repeater are indexed. The header row is index -1; other rows are indexed beginning with 0. This row index is passed to the OnItemCommand subprogram through its RepeaterCommandEventArgs argument to identify the row on which a button is clicked and to differentiate among the several rows of controls comprising the Repeater. The row index along with a control's id give a unique identifier to each control. It becomes a matter of using the Repeater's FindControl() method to locate individual controls for editing. The first portion of the Edit_Record subprogram illustrates this process.
Sub Edit_Record (Src As Object, Args As RepeaterCommandEventArgs) Dim BookID As TextBox = Args.Item.FindControl("BookID") Dim BookType As DropDownList = Args.Item.FindControl("BookType") Dim BookTitle As TextBox = Args.Item.FindControl("BookTitle") Dim BookAuthor As TextBox = Args.Item.FindControl("BookAuthor") Dim BookDescription As TextBox = Args.Item.FindControl("BookDescription") Dim BookPrice As TextBox = Args.Item.FindControl("BookPrice") Dim BookQty As TextBox = Args.Item.FindControl("BookQty") Dim BookSale As CheckBox = Args.Item.FindControl("BookSale") ... End Sub
The argument passed to the subprogram includes a reference to the row (Item) on which a button is clicked. This reference includes an index for the row (Item.ItemIndex ), and it contains the collection of controls making up the row. These controls are accessed by the row's FindControl() method, supplying the id of the control of interest. For example, the reference Args.Item.FindControl("BookID") in the above example locates the TextBox with the identification "BookID" on whichever row a button is clicked. When this reference is assigned to a variable of the same control type, then the script can access properties associated with that particular control in the Repeater.
Dim BookID As TextBox = Args.Item.FindControl("BookID")
The above statement permits use of the reference BookID.Text to access the value contained in the TextBox with id="BookID" on whichever row a command button is clicked. In the preceding script, all controls along the reference row are found and assigned to variables of like types. This makes it easy for the script to refer to all data values appearing along that row of the Repeater and to involve them in database insert, update, and delete operations.
Repeater Editing
The remainder of the Edit_Record subprogram to perform insert, update, and delete operations is shown below.
Sub Edit_Record (Src As Object, Args As RepeaterCommandEventArgs) Dim BookID As TextBox = Args.Item.FindControl("BookID") Dim BookType As DropDownList = Args.Item.FindControl("BookType") Dim BookTitle As TextBox = Args.Item.FindControl("BookTitle") Dim BookAuthor As TextBox = Args.Item.FindControl("BookAuthor") Dim BookDescription As TextBox = Args.Item.FindControl("BookDescription") Dim BookPrice As TextBox = Args.Item.FindControl("BookPrice") Dim BookQty As TextBox = Args.Item.FindControl("BookQty") Dim BookSale As CheckBox = Args.Item.FindControl("BookSale") If Args.CommandName = "Update" Then Dim SQLString As String = "UPDATE Books SET " & _ "BookType = '" & BookType.SelectedValue & "', " & _ "BookTitle = '" & BookTitle.Text & "', " & _ "BookAuthor = '" & BookAuthor.Text & "', " & _ "BookDescription = '" & BookDescription.Text & "', " & _ "BookPrice = '" & BookPrice.Text & "', " & _ "BookQty = '" & BookQty.Text & "', " & _ "BookSale = " & BookSale.Checked & " " & _ "WHERE BookID = '" & BookID.Text & "'" BookSource.UpdateCommand = SQLString BookSource.Update() EditMessage.Text = "Record " & BookID.Text & " updated" End If If Args.CommandName = "Insert" Then Dim SQLString As String = "INSERT INTO Books " & _ "(BookID, BookType, BookTitle, BookAuthor, BookDescription, " & _ "BookPrice, BookQty, BookSale) VALUES (" & _ "'" & BookID.Text & "', " & _ "'" & BookType.SelectedValue & "', " & _ "'" & BookTitle.Text & "', " & _ "'" & BookAuthor.Text & "', " & _ "'" & BookDescription.Text & "', " & _ "'" & BookPrice.Text & "', " & _ "'" & BookQty.Text & "', " & _ BookSale.Checked & ")" BookSource.InsertCommand = SQLString BookSource.Insert() EditMessage.Text = "Record " & BookID.Text & " inserted" End If If Args.CommandName = "Delete" Then Dim SQLString As String = "DELETE FROM Books " _ & "WHERE BookID = '" & BookID.Text & "'" BookSource.DeleteCommand = SQLString BookSource.Delete() EditMessage.Text = "Record " & BookID.Text & " deleted" End If End Sub
The subprogram needs to know which button on the row was clicked in order to perform appropriate processing. Recall that the buttons include CommandNames to identify whether to perform "Insert," "Update," or "Delete" operations. The CommandName of the clicked button is contained in the CommandName argument passed to the subprogram. Therefore, by testing Args.CommandName the subprogram can determine which processing action to take.
Inserting Records
If the clicked button has the CommandName of "Insert," then the section of the script to add a new record to the database is performed. This section is repeated below.
If Args.CommandName = "Insert" Then Dim SQLString As String = "INSERT INTO Books " & _ "(BookID, BookType, BookTitle, BookAuthor, BookDescription, " & _ "BookPrice, BookQty, BookSale) VALUES (" & _ "'" & BookID.Text & "', " & _ "'" & BookType.SelectedValue & "', " & _ "'" & BookTitle.Text & "', " & _ "'" & BookAuthor.Text & "', " & _ "'" & BookDescription.Text & "', " & _ "'" & BookPrice.Text & "', " & _ "'" & BookQty.Text & "', " & _ BookSale.Checked & ")" BookSource.InsertCommand = SQLString BookSource.Insert() EditMessage.Text = "Record " & BookID.Text & " inserted" End If
Processing involves composing an SQL statement to INSERT a new record into the Books table of the database. The SQL statement is assigned to the InsertCommand property of the AccessDataSource for the Repeater, and its Insert() method is called.
Recall from above that controls along the insert row of the Repeater (along the row containing the insert button that is clicked) have been found and assigned to reference variables. For TextBoxes along the row, their Text properties point to their entered values; for the DropDownList, its SelectedValue property is accessed; for the CheckBox, its Checked property is its value. These row values are concatenated inside fixed text strings to compose an appropriate INSERT statement that is issued through the AccessDataSource. After record insertion, the Repeater is automatically re-bound to the data source to display the added record.
Updating Records
A similar process is followed to update existing records. This portion of the Edit_Records subprogram is repeated below.
If Args.CommandName = "Update" Then Dim SQLString As String = "UPDATE Books SET " & _ "BookType = '" & BookType.SelectedValue & "', " & _ "BookTitle = '" & BookTitle.Text & "', " & _ "BookAuthor = '" & BookAuthor.Text & "', " & _ "BookDescription = '" & BookDescription.Text & "', " & _ "BookPrice = '" & BookPrice.Text & "', " & _ "BookQty = '" & BookQty.Text & "', " & _ "BookSale = " & BookSale.Checked & " " & _ "WHERE BookID = '" & BookID.Text & "'" BookSource.UpdateCommand = SQLString BookSource.Update() EditMessage.Text = "Record " & BookID.Text & " updated" End If
If the CommandName of the clicked button is "Update," then an SQL UPDATE statement is composed, inserting data values from controls along the same row as the clicked button. Notice that the BookID (key) field is not updated since it is used to locate the database record to update. In fact, the BookID TextBoxes on the edit rows do not permit changing these numbers. They all have ReadOnly="True" property settings.
After the UPDATE statement is composed, it is assigned to the UpdateCommand property of the AccessDataSource and its Update() method is called. After the record is changed, the Repeater redisplays the changes.
Deleting Records
Deleting the record on the row containing the clicked "Delete" button is a matter of composing an SQL DELETE statement that includes the value from the BookID TextBox on that row. This statement is assigned to the DeleteCommand property of the AccessDataSource and its Delete() method is called. The redisplayed Repeater is absent the deleted record.
If Args.CommandName = "Delete" Then Dim SQLString As String = "DELETE FROM Books " _ & "WHERE BookID = '" & BookID.Text & "'" BookSource.DeleteCommand = SQLString BookSource.Delete() EditMessage.Text = "Record " & BookID.Text & " deleted" End If
Record Validation
In this example application no validation is perform on inserted or updated fields. These routines are left out to simplify description of the editing routines. It is a simple matter, however, to insert validation routines inside the appropriate sections of code. The following portion of script for inserting new records is augmented with selected validation tests that have been used in previous examples.
If Args.CommandName = "Insert" Then Dim ValidRecord As Boolean = True If BookID.Text = "" Then ValidRecord = False EditMessage.Text = "-- Missing BookID. Record not added." End If If Not IsNumeric(BookPrice.Text) Then ValidRecord = False EditMessage.Text = "-- Price is not numeric. Record not added." End If If Not IsNumeric(BookQty.Text) Then ValidRecord = False EditMessage.Text = "-- Quantity is not numeric. Record not added" End If If ValidRecord = True Then Dim SQLString As String = "INSERT INTO Books " & _ "(BookID, BookType, BookTitle, BookAuthor, BookDescription, " & _ "BookPrice, BookQty, BookSale) VALUES (" & _ "'" & BookID.Text & "', " & _ "'" & BookType.SelectedValue & "', " & _ "'" & BookTitle.Text & "', " & _ "'" & BookAuthor.Text & "', " & _ "'" & BookDescription.Text & "', " & _ "'" & BookPrice.Text & "', " & _ "'" & BookQty.Text & "', " & _ BookSale.Checked & ")" BookSource.InsertCommand = SQLString BookSource.Insert() EditMessage.Text = "Record " & BookID.Text & " inserted" End If End If
Prior to writing a new record to the database, three tests are made on the BookID, BookPrice, and BookQty fields of the insert row. Initially, a validation flag (ValidRecord) is set to True. If any of the validation tests fails, then the flag is changed to False and no new record is written to the database. A similar script setup can be used for editing records.