Using Other Controls to Edit Data

As we saw in Figures 9.1 through 9.4, the DataGrid provides a TextBox Web control as a default editing interface for a column. However, there are times when the data we are editing cannot be easily edited via a simple TextBox. For example, we might want to use a multiline TextBox, or perhaps a DropDownList, or CheckBoxList. In addition, we might want to add validation controls to the editing interface, which are not added by the DataGrid's default editing interface.

Our DataGrid's Comment column is a good example of when a standard TextBox Web control might not be the optimal editing interface. Because the Comment column can accept inputs of up to 255 characters, it might be better to use a multiline TextBox.

We can specify the HTML and Web controls to be used for a column's editing interface by using a TemplateColumn control instead of a BoundColumn control. Recall from Chapter 3, "Customizing the HTML Output," that the TemplateColumn control can contain a number of templates. The ItemTemplate, for example, is the template used when the column is rendered in a standard row. The TemplateColumn can also include an EditItemTemplate, which, as its name suggests, is the template used when a column is rendered in edit mode.

Listing 9.4 contains the source code for an ASP.NET Web page that uses a custom editing interface for the Comment column. Most of the code in Listing 9.4 is identical to that in Listing 9.3, and has therefore been omitted for brevity. The only parts new to Listing 9.4 are the DataGrid declaration (specifically the change from a BoundColumn control to a TemplateColumn control for the Comment column) and the dgComment_UpdateRow event handler. Because of the change in the Comment column, we have to alter the way we reference the TextBox for the Comment column in the dgComment_UpdateRow event handler.

Listing 9.4 A Custom Editing Interface Is Employed for the Comment Column
  1: <%@ import Namespace="System.Data" %>   2: <%@ import Namespace="System.Data.SqlClient" %>   3: <script runat="server" language="VB">   4:   ' ... The Page_Load event handler, BindData() subroutine,   5:   ' ... dgComment_EditRow, and dgComment_CancelRow event handlers   6:   ' ... are identical to the ones presented in Listing 9.3 ...   7:   8:     Sub dgComments_UpdateRow(sender As Object, e As DataGridCommandEventArgs)   9:       'Get information from columns...  10:       ...  11:       Dim commentTextBox as TextBox = e.Item.Cells(3). FindControl("txtComment")  12:       ...  13:  14:       ' The remainder of the dgComment_UpdateRow eventhandler is identical  15:       ' to the dgComment_UpdateRow event handler in Listing 9.3 ...  16:     End Sub  17: </script>  18:  19: <form runat="server">  20:   <asp:DataGrid runat="server"   21:       Font-Name="Verdana" Font-Size="9pt" CellPadding="5"  22:       AlternatingItemStyle-BackColor="#dddddd"  23:       AutoGenerateColumns="False" DataKeyField="CommentID"  24:       OnEditCommand="dgComments_EditRow"  25:       OnUpdateCommand="dgComments_UpdateRow"  26:       OnCancelCommand="dgComments_CancelRow">  27:   28:     <HeaderStyle BackColor="Navy" ForeColor="White" Font-Size="13pt"  29:               Font-Bold="True" HorizontalAlign="Center" />  30:  31:     <Columns>  32:       <asp:EditCommandColumn ButtonType="LinkButton" HeaderText="Edit"  33:             EditText="Edit" UpdateText="Update" CancelText="Cancel" />  34:       <asp:BoundColumn DataField="CommentID"  35:                 HeaderText="Comment ID" ReadOnly="True" />  36:       <asp:BoundColumn DataField="Name" HeaderText="Name" />  37:       <asp:TemplateColumn HeaderText="Comment">  38:         <ItemTemplate>  39:           <%# DataBinder.Eval(Container.DataItem, "Comment") %>  40:         </ItemTemplate>  41:         <EditItemTemplate>  42:           <asp:TextBox runat="server"  TextMode="MultiLine"  43:                    Columns="40" Rows="6" MaxLength="255"  44:                    Text='<%# DataBinder.Eval(Container.DataItem, "Comment") %>' />  45:         </EditItemTemplate>  46:       </asp:TemplateColumn>  47:       <asp:BoundColumn DataField="DateAdded" HeaderText="Date Added"  48:                 ReadOnly="True" />  49:     </Columns>  50:   </asp:DataGrid>  51: </form> 

Let's first look at the differences in the DataGrid's declaration. The Data declaration in Listing 9.4 is identical to that in Listing 9.3 save for lines 37 through 46, which specify that the DataGrid's Comment column should be rendered using a TemplateColumn as opposed to a BoundColumn.

Recall that a TemplateColumn can have multiple templates. The ItemTemplate is the template used when rendering the column for a normal row. The Comment column's ItemTemplate is defined on lines 38 through 40. This ItemTemplate is quite simple, it just emits the value of the Comment field from the DataSource. (If you need to brush up on the data-binding syntax (<%# ... %>), consider looking over Chapters 2 and 3 once again.)

The EditItemTemplate (lines 41 through 45) is the template used when the column is being rendered in edit mode. This occurs when the index of the DataGrid row being rendered is equal to the DataGrid's EditItemIndex property. In Listing 9.4, the EditItemTemplate specifies that a multiline TextBox control with 40 characters and 6 rows should be used. Furthermore, the TextBox's MaxLength property is set to 255, which is an attribute recognized by later versions of Internet Explorer that limits the user's input to 255 characters.

On line 44, the TextBox's Text property is set to the value of the Comment field of the DataSource using data-binding syntax. By setting the Text property, when the user opts to edit a particular row, the value of the row's Comment field will appear in the multiline TextBox.

CAUTION

If you forget to set TextBox's Text property as was done on line 44, when the user clicks a row's Edit button, the multiline TextBox representing the value of the Comment field will be blank.


Also note that in the multiline TextBox we specify the TextBox's ID property, setting it to txtComment. We do this so that the TextBox control can be easily referenced in the dgComments_UpdateRow event handler. (Recall that we need to reference this TextBox's value in the dgComments_UpdateRow event handler so that the database can be updated with the values entered by the user.)

TIP

To make a TemplateColumn read-only, just don't provide an EditItemTemplate for the TemplateColumn.


The other interesting part to the code in Listing 9.4 is in the dgComments_UpdateRow event handler. Because the Comment column uses a TemplateColumn as opposed to a BoundColumn, the syntax for retrieving the value of the Comment column's TextBox is a bit different. The reason is because the TemplateColumn is rendered as a series of controls that are then added to the DataGrid's corresponding TableCell. All HTML content in a TemplateColumn's template is rendered as a LiteralControl. Therefore, the EditItemTemplate in Listing 9.4 is comprised of three child controls: a LiteralControl, representing the HTML whitespace that appears before the TextBox Web control; the TextBox Web control txtContent; and a LiteralControl, representing the HTML whitespace that appears after the TextBox Web control.

Recall that the code used to retrieve the TextBox value in Listing 9.3 was as follows:

 Dim commentTextBox as TextBox = e.Item.Cells(3).Controls(0) 

However, because the first control of the Comments TableCell is a LiteralControl representing the whitespace before the TextBox, e.Item.Cells(3).Controls(0) will return a LiteralControl, not a TextBox control.

Although we could adjust the dgComments_UpdateRow event handler code to use

 Dim commentTextBox as TextBox = e.Item.Cells(3).Controls(1) 

This code might need to be changed if we add more HTML or Web controls to the Comment column's EditItemTemplate. A more elegant solution is to use the FindControl(controlID ) method to explicitly reference the TableCell's child control, whose ID is set to txtComment. This is accomplished in the dgComments_UpdateRow event handler in Listing 9.4 on line 11.

The remaining code for the dgComments_UpdateRow event handler is the same as it was in Listing 9.3. That is, after we have correctly referenced the Comment column's TextBox, we proceed as we did in Listing 9.3 in updating the database with the changes.

Figure 9.5 contains a screenshot of Listing 9.4 in action. Note that the Comment column's editing interface is rendered as a multiline TextBox.

Figure 9.5. The Comment column uses a customized editing interface.

graphics/09fig05.gif

Listing 9.4 illustrates how to add a custom editing interface to a particular DataGrid column. Note that when adding the custom editing interface, you need to be certain to do two things.

First, you must be certain that the custom editing interface is correctly set to the value in the corresponding DataSource field when it's selected for editing. For example, in Listing 9.4 we set the TextBox's Text property to the value of the DataSource's Comment field so that when the user edited a particular row, the row's Comment value would appear in the multiline TextBox. Regardless of what custom editing interface you provide, you will need to be certain to set its initial value to the value of the field it's representing.

Second, you must make certain that you correctly reference the custom editing interface's data in the event handler that is executed when the Update button is clicked. For example, in Listing 9.4 we needed to use the FindControl method to get a reference to the Comment column's TextBox.

A DataGrid column's custom editing interface is limited only by your imagination and programming skills. You can add TextBoxes, DropDownLists, RadioButtons, CheckBoxes, CheckBoxLists, RadioButtonLists, and so on. In fact, in the next section we will examine how to add a Calendar Web control to a DataGrid column's custom editing interface. Regardless of the editing interface you think up, just be certain that you are able to set its initial value to the value of the corresponding DataSource field, and after the user clicks Update, you are able to read its data.

Using a Calendar Control in a Customized Editing Interface

If the data we are displaying in the DataGrid has a column that is a date, we can provide a rich customized editing interface to the date column by utilizing the ASP.NET Calendar control. The ASP.NET Calendar Web control displays a calendar in month form, enabling the user to select a particular day of any month of any year. (If you are not familiar with the Calendar control, you might want to read "The Calendar Web Control" referenced in the "On the Web" section at the end of this chapter before continuing.)

For our Comments table, there is a DateAdded field that is a DateTime field in SQL Server. However, let's imagine that we are only interested in the actual date the comment was posted, not the date and time. In this scenario, we could use a Calendar Web control for the editing interface for this column.

NOTE

If we were interested in both the date and time, we might want to use two Web controls in the editing interface: a Calendar Web control, enabling the user to select the date, and a some other Web control to enable the user to select the time. This other Web control could be as simple as a TextBox, or as involved as a custom Web control written expressly for time inputs.


Recall that to provide a customized editing interface, we have to use a TemplateColumn as opposed to a BoundColumn. Hence, our first step is altering our DataGrid's declaration from Listing 9.4 to use a TemplateColumn for the DateAdded column as opposed to a BoundColumn. In this TemplateColumn, we might want to have the ItemTemplate display only the date part of the DateAdded field, as opposed to the date and time. In our EditItemTemplate, we will use a Calendar Web control. The updated DataGrid declaration can be found in Listing 9.5.

Listing 9.5 The DataGrid Declaration Has Been Altered to Include a TemplateColumn for the DateAdded Column
  1: <form runat="server">   2:   <asp:DataGrid runat="server"    3:       Font-Name="Verdana" Font-Size="9pt" CellPadding="5"   4:       AlternatingItemStyle-BackColor="#dddddd"   5:       AutoGenerateColumns="False" DataKeyField="CommentID"   6:       OnEditCommand="dgComments_EditRow"   7:       OnUpdateCommand="dgComments_UpdateRow"   8:       OnCancelCommand="dgComments_CancelRow">   9:  10:     <HeaderStyle BackColor="Navy" ForeColor="White" Font-Size="13pt"  11:               Font-Bold="True" HorizontalAlign="Center" />  12:  13:     <Columns>  14:       <asp:EditCommandColumn ButtonType="LinkButton" HeaderText="Edit"  15:             EditText="Edit" UpdateText="Update" CancelText="Cancel" />  16:       <asp:BoundColumn DataField="CommentID"  17:                 HeaderText="Comment ID" ReadOnly="True" />  18:       <asp:BoundColumn DataField="Name" HeaderText="Name" />  19:       <asp:TemplateColumn HeaderText="Comment">  20:         <ItemTemplate>  21:           <%# DataBinder.Eval(Container.DataItem, "Comment") %>  22:         </ItemTemplate>  23:         <EditItemTemplate>  24:           <asp:TextBox runat="server"  TextMode="MultiLine"  25:                    Columns="40" Rows="6" MaxLength="255"  26:                    Text='<%# DataBinder.Eval(Container.DataItem, "Comment") %>' />  27:         </EditItemTemplate>  28:       </asp:TemplateColumn>  29:       <asp:TemplateColumn HeaderText="Date Added"  30:            ItemStyle-HorizontalAlign="Center">  31:         <ItemTemplate>  32:           <%# String.Format("{0:d}", Convert.ToDateTime (DataBinder.Eval(Container.DataItem, "DateAdded"))) %>  33:         </ItemTemplate>  34:         <EditItemTemplate>   35:           <asp:Calendar  runat="server"  36:                 SelectedDate='<%# Convert.ToDateTime (DataBinder.Eval(Container.DataItem, "DateAdded")) %>'  37:                 VisibleDate='<%# Convert.ToDateTime (DataBinder.Eval(Container.DataItem, "DateAdded")) %>' />  38:         </EditItemTemplate>  39:       </asp:TemplateColumn>  40:     </Columns>  41:   </asp:DataGrid>  42: </form> 

The added TemplateColumn can be found in lines 29 through 39. Note that in the DateAdded column's ItemTemplate, we format the value of the DateAdded field so that only the date part is displayed. To accomplish this, we use the String.Format method (line 32).

Recall that when providing a customized editing interface, there are two tasks we must concern ourselves with. The first is ensuring that the Web control (or controls) used to implement the customized editing interface have their initial value set to the value of the DataSource field they are representing. We accomplish this with the Calendar control in lines 36 and 37, where we set the SelectedDate and VisibleDate properties.

The SelectedDate property indicates what date is selected by default on the Calendar Web control. Clearly, we want the Calendar's SelectedDate property set to the current value of the row's DateAdded field. The VisibleDate property specifies what month and year are displayed in the Calendar control; we want this property also set to the current value of the row's DateAdded field so that the month and year of the DateAdded field is displayed in the Calendar.

CAUTION

If you fail to set the VisibleDate property, the Calendar control will display the current month and year by default, regardless of the value of the SelectedDate property. That is, even if the SelectedDate property is set to October 10, 2002, if the current date is April 1, 2003, the Calendar control will display the calendar for April 2003. Of course, the user can cycle back to October 2002, but this would likely be inconvenient.


By setting these two properties of the Calendar control, we have achieved our first goal: ensuring that the Web control used to implement the customized editing interface has its initial value set to the value of the DataSource field it is representing.

At this point, when the user clicks the Edit button for a row in the DataGrid, the row will become editable. The Name column will have a standard TextBox, the Comment column will have a multiline TextBox (refer back to Listing 9.4 for more information), and the DateAdded column will have a Calendar Web control displayed. The user can switch the months of the Calendar Web control and click on the various days. Each time the user switches to a different Calendar month or selects a date from the Calendar control, the ASP.NET Web page is posted back. However, the row being edited remains in editing mode, because the DataGrid's EditItemIndex property has not changed.

Each time the user clicks a specific date in the Calendar, the Calendar control's SelectedDate property is updated to reflect the currently selected date. After the user has chosen an appropriate date (as well as updated the Name and/or Comment columns if so desired), he can click the Update button to commit the changes to the database. Clicking the Update button will cause the ASP.NET Web page to be posted back and the DataGrid's UpdateCommand event to fire. This will cause the dgComments_UpdateRow event handler to execute.

Recall that when adding a customized editing interface, our second task is to alter the event handler that fires when the Update button is clicked, so that the value entered for the customized editing interface can be read and inserted into the database. To accomplish this, we need to update our dgComments_UpdateRow event handler. Specifically, we need to provide a means by which the Calendar control can be accessed and have its SelectedDate property read.

The code in Listing 9.6 contains the updated code for the dgComments_UpdateRow event handler.

Listing 9.6 The SelectedDate Property of the Calendar Control Is Used to Update the Database
  1:     Sub dgComments_UpdateRow(sender As Object, e As DataGridCommandEventArgs)   2:       'Get information from columns...   3:       Dim nameTextBox as TextBox = e.Item.Cells(2).Controls(0)   4:       Dim commentTextBox as TextBox = e.Item.Cells(3). FindControl("txtComment")   5:       Dim dateAdded as Calendar = e.Item.Cells(4).FindControl("calDate")   6:   7:       Dim iCommentID as Integer = dgComments.DataKeys(e.Item.ItemIndex)   8:   9:  10:       'Update the database...  11:       Dim strSQL as String  12:       strSQL = "UPDATE Comments SET Name = @NameParam, DateAdded = @DateAddedParam, " & _  13:                "Comment = @CommentParam WHERE CommentID = @CommentIDParam"   14:  15:       Const strConnString as String = "server=localhost;uid=sa;pwd=; database=pubs"  16:       Dim objConn as New SqlConnection(strConnString)  17:  18:       Dim objCmd as New SqlCommand(strSQL, objConn)  19:  20:       Dim nameParam as New SqlParameter("@NameParam", SqlDbType.VarChar, 50)  21:       Dim commentParam as New SqlParameter("@CommentParam", SqlDbType. VarChar, 255)  22:       Dim dateAddedParam as New SqlParameter("@DateAddedParam", SqlDbType. DateTime)  23:       Dim commentIDParam as New SqlParameter("@CommentIDParam", SqlDbType.Int, 4)  24:  25:       nameParam.Value = nameTextBox.Text  26:       objCmd.Parameters.Add(nameParam)  27:  28:       commentParam.Value = commentTextBox.Text  29:       objCmd.Parameters.Add(commentParam)  30:  31:       dateAddedParam.Value = dateAdded.SelectedDate  32:       objCmd.Parameters.Add(dateAddedParam)  33:  34:       commentIDParam.Value = iCommentID  35:       objCmd.Parameters.Add(commentIDParam)  36:  37:       'Issue the SQL command  38:       objConn.Open()  39:       objCmd.ExecuteNonQuery()  40:       objConn.Close()  41:  42:       dgComments.EditItemIndex = -1  43:       BindData()  44:     End Sub 

The bold lines in Listing 9.6 represent the lines of code updated from the dgComments_UpdateRow event handler from Listing 9.4.

On line 5, the Calendar Web control is referenced by the local variable dateAdded. The FindControl(controlID ) technique is used here as it was to reference the Comment column TextBox (see Listing 9.4, or line 4 in Listing 9.6). The SQL statement on lines 12 and 13 is also updated to update the selected database record's DateAdded field.

Because the SQL statement is parameterized, we need to create a parameter for the @DateAddedParam parameter. This is accomplished on line 22. On lines 31 and 32, we set the Value of this parameter to the SelectedDate property of the Calendar control and then add the parameter to the Parameters collection of the SqlCommand object objCmd. The remainder of the dgComments_UpdateRow event handler is identical to that in Listing 9.4.

Figure 9.6 shows a screenshot of the updated code presented in Listings 9.5 and 9.6. Specifically, the screenshot is of when a user has clicked on the Edit button for a row. Note that the DateAdded column is rendered as a Calendar Web control. Also notice that the DateAdded column values that are not being edited display only the date part, not the date and time.

Figure 9.6. The customized editing interface for the DateAdded column uses a Calendar control.

graphics/09fig06.gif



ASP. NET Data Web Controls Kick Start
ASP.NET Data Web Controls Kick Start
ISBN: 0672325012
EAN: 2147483647
Year: 2002
Pages: 111

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net