ptg 584 CHAPTER 12 Using the DetailsView and FormView Controls FIGURE 12.7 Editing a record with the DetailsView control. Updating Data with the DetailsView Control You can use the DetailsView control to update existing database records. To update an existing record, assign the value True to the DetailsView control’s AutoGenerateEditButton property, as illustrated in Listing 12.10 (see Figure 12.7). LISTING 12.10 ShowUpdate.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Update</title> </head> <body> <form id=”form1” runat=”server”> <div> From the Library of Wow! eBook ptg 585 Using the DetailsView Control 12 <asp:DetailsView id=”dtlMovies” DataKeyNames=”Id” AutoGenerateEditButton=”true” AllowPaging=”true” DataSourceID=”srcMovies” Runat=”server” /> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title,Director,InTheaters FROM Movies” UpdateCommand=”UPDATE Movies SET Title=@Title,Director=@Director, InTheaters=@InTheaters WHERE Id=@Id” Runat=”server” /> </div> </form> </body> </html> When you open the page in Listing 12.10, the record appears in Read Only mode. You can click the Edit button to switch the DetailsView into Edit mode and update the record. The DetailsView control includes a DataKeyNames property and an AutoGenerateEditButton property. The DataKeyNames property contains the name of the primary key column. The AutoGenerateEditButton property automatically generates the user interface for editing the record. The SqlDataSource control includes an UpdateCommand. The UpdateCommand updates the Title, Director, and InTheaters database columns. If you want the DetailsView control to initially appear in Edit mode, you can set the DetailsView control’s DefaultMode property to the value Edit. For example, the page in Listing 12.11 contains a Master/Detail form. If you select any of the records in GridView, you can edit the record with the DetailsView control (see Figure 12.8). From the Library of Wow! eBook ptg 586 CHAPTER 12 Using the DetailsView and FormView Controls FIGURE 12.8 Displaying a Master/Detail form with the DetailsView control. LISTING 12.11 MasterDetailEdit.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> void Page_Load() { if (!Page.IsPostBack) grdMovies.SelectedIndex = 0; } protected void dtlMovies_ItemUpdated(object sender, DetailsViewUpdatedEventArgs ➥ e) { grdMovies.DataBind(); } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <style type=”text/css”> html From the Library of Wow! eBook ptg 587 Using the DetailsView Control 12 { background-color:silver; font:14px Georgia,Serif; } .content { margin:auto; width:600px; background-color:white; } .column { float:left; width:250px; } .selectedRow { background-color:yellow; } </style> <title>Master/Detail Edit</title> </head> <body> <form id=”form1” runat=”server”> <div class=”content”> <div class=”column”> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” DataKeyNames=”Id” AutoGenerateSelectButton=”true” SelectedRowStyle-CssClass=”selectedRow” Runat=”server” /> </div> <div class=”column”> <asp:DetailsView id=”dtlMovies” DefaultMode=”Edit” AutoGenerateEditButton=”true” AllowPaging=”true” DataSourceID=”srcMovieDetails” DataKeyNames=”Id” Runat=”server” OnItemUpdated=”dtlMovies_ItemUpdated” /> From the Library of Wow! eBook ptg 588 CHAPTER 12 Using the DetailsView and FormView Controls <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title FROM Movies” Runat=”server” /> </div> <asp:SqlDataSource id=”srcMovieDetails” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title,Director,InTheaters FROM Movies WHERE Id=@MovieId” UpdateCommand=”UPDATE Movies SET Title=@Title,Director=@Director, InTheaters=@InTheaters WHERE Id=@Id” Runat=”server”> <SelectParameters> <asp:ControlParameter Name=”MovieId” ControlID=”grdMovies” /> </SelectParameters> </asp:SqlDataSource> </div> </form> </body> </html> The DetailsView control includes a DefaultMode property set to the value Edit. When you select a record, the record displays by DetailsView in Edit mode by default. Using Templates When Editing By default, you don’t get any validation when editing records with the DetailsView control. In other words, there is nothing to prevent you from attempting to submit a null value to a database column that does not accept null values. If you need to perform vali- dation, you need to use templates with the DetailsView control. The page in Listing 12.12 uses TemplateFields for the Title and BoxOfficeTotals columns. Both TemplateFields contain a RequiredFieldValidator. The BoxOfficeTotals column also includes a CompareValidator to check whether the value entered is a currency value (see Figure 12.9). From the Library of Wow! eBook ptg 589 Using the DetailsView Control 12 FIGURE 12.9 Using a template when editing with the DetailsView control. LISTING 12.12 TemplateEdit.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Template Edit</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:DetailsView id=”dtlMovies” AutoGenerateRows=”false” AutoGenerateEditButton=”true” AllowPaging=”true” DefaultMode=”Edit” DataSourceID=”srcMovies” DataKeyNames=”Id” Runat=”server”> From the Library of Wow! eBook ptg 590 CHAPTER 12 Using the DetailsView and FormView Controls <Fields> <asp:TemplateField HeaderText=”Title:”> <EditItemTemplate> <asp:TextBox id=”txtTitle” Text=’<%# Bind(“Title”) %>’ runat=”server” /> <asp:RequiredFieldValidator id=”reqTitle” ControlToValidate=”txtTitle” Text=”(required)” Display=”Dynamic” Runat=”server” /> </EditItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText=”Box Office Totals:”> <EditItemTemplate> <asp:TextBox id=”txtBoxOfficeTotals” Text=’<%# Bind(“BoxOfficeTotals”, “{0:f}”) %>’ runat=”server” /> <asp:RequiredFieldValidator id=”reqBoxOfficeTotals” ControlToValidate=”txtBoxOfficeTotals” Text=”(required)” Display=”Dynamic” Runat=”server” /> <asp:CompareValidator id=”cmpBoxOfficeTotals” ControlToValidate=”txtBoxOfficeTotals” Text=”(invalid)” Display=”Dynamic” Operator=”DataTypeCheck” Type=”currency” Runat=”server” /> </EditItemTemplate> </asp:TemplateField> </Fields> </asp:DetailsView> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title,BoxOfficeTotals FROM Movies” UpdateCommand=”UPDATE Movies SET Title=@Title, BoxOfficeTotals=@BoxOfficeTotals WHERE Id=@Id” From the Library of Wow! eBook ptg 591 Using the DetailsView Control 12 Runat=”server” /> </div> </form> </body> </html> If you attempt to edit a record, and you do not provide a value for the Title or BoxOfficeTotals columns, a validation error displays. Also, if you enter anything other than a currency amount for the BoxOfficeTotals column, a validation error message displays. Handling Concurrency Issues What happens when two users edit the same record at the same time? By default, the last user to update the database record wins. In other words, one user can overwrite changes made by another user. Imagine that Sally opens a page to edit a database record. After opening the page, Sally leaves for her 2-week vacation in Las Vegas. While Sally is vacationing, Jim edits the same record and submits his changes. When Sally returns from vacation, she submits her changes. Any modifications that Jim makes are overwritten by Sally’s changes. If you need to prevent this scenario, you can take advantage of optimistic concurrency. The SqlDataSource control’s ConflictDetection property supports the following two values: . CompareAllValues . OverwriteChanges By default, the ConflictDetection property has the value OverwriteChanges. If you set this property to the value CompareAllValues, the SqlDataSource tracks both the original and modified versions of each column. For example, the page in Listing 12.13 doesn’t enable a user to update a record when the original record has been modified after the user has opened the page. LISTING 12.13 Concurrency.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> protected void srcMovies_Updated(object sender, SqlDataSourceStatusEventArgs e) { if (e.AffectedRows == 0) lblMessage.Text = “Could not update record”; From the Library of Wow! eBook ptg 592 CHAPTER 12 Using the DetailsView and FormView Controls } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Concurrency</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:Label ID=”lblMessage” EnableViewState=”false” runat=”server” /> <asp:DetailsView id=”dtlMovies” DataKeyNames=”Id” AutoGenerateEditButton=”true” AllowPaging=”true” DataSourceID=”srcMovies” Runat=”server” /> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title,Director,InTheaters FROM Movies” UpdateCommand=”UPDATE Movies SET Title=@Title,Director=@Director,InTheaters= WHERE Title=@original_Title AND Director=@original_Director AND InTheaters=@InTheaters AND Id=@original_Id” ConflictDetection=”CompareAllValues” OldValuesParameterFormatString=”original_{0}” Runat=”server” OnUpdated=”srcMovies_Updated” /> </div> </form> </body> </html> Notice the contents of UpdateCommand in Listing 12.13. The current values are compared against the original values for each database column when updating a record. If the current and original values don’t match, the record is not updated. From the Library of Wow! eBook ptg 593 Using the DetailsView Control 12 The SqlDataSource has both its ConflictDetection and OldValuesParameterFormat String properties set. The OldValuesParameterFormatString specifies the prefix added to the parameters that represent the original field values. If there is a concurrency conflict, the e.AffectedRows property passed to the Updated event handler will have the value 0. In Listing 12.13, a message is displayed in a Label control when a record cannot be updated. Inserting Data with the DetailsView Control You can use the DetailsView control to insert new records into a database table. For example, the page in Listing 12.14 enables you to insert a new record into the Movies database table. LISTING 12.14 ShowInsert.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Insert</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:DetailsView id=”dtlMovies” AllowPaging=”true” DataSourceID=”srcMovies” AutoGenerateInsertButton=”true” Runat=”server” /> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Title,Director,InTheaters FROM Movies” InsertCommand=”INSERT Movies (Title,Director,InTheaters) VALUES (@Title,@Director, Runat=”server” /> </div> </form> </body> </html> From the Library of Wow! eBook . Text=”(invalid)” Display=”Dynamic” Operator=”DataTypeCheck” Type=”currency” Runat=”server” /> </EditItemTemplate> < /asp: TemplateField> </Fields> < /asp: DetailsView> < ;asp: SqlDataSource. Display=”Dynamic” Runat=”server” /> </EditItemTemplate> < /asp: TemplateField> < ;asp: TemplateField HeaderText=”Box Office Totals:”> <EditItemTemplate> < ;asp: TextBox id=”txtBoxOfficeTotals” Text=’<%#. example, the page in Listing 12. 14 enables you to insert a new record into the Movies database table. LISTING 12. 14 ShowInsert.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD