[referrenced]Master/Detail Editing - DetailsView
http://msconline.maconstate.edu/tutorials/ASPNET2/ASPNET09/aspnet09-05.aspx
Record editing with a single DetailsView or FormView works fine for small database tables requiring few pages to navigate. For large recordsets, though, it may be difficult to locate particular records by paging through them sequentially. What is required is a table of contents to quickly locate records of interest, and a form for editing those that are found. These requirements are easily provided in a master/detail setup. In the following example, a GridView presents an index to all records in eCommerce.mdb database; a linked DetailsView gives editing access to individual records.
Note that making actual changes to the eCommerce.mdb database is not permitted in these tutorials; however, all other functions work as expected.
Number | Name | ||
---|---|---|---|
BU1111 | Microsoft Office Professional 2003 | ||
BU2222 | WordPerfect Office 12 | ||
BU3333 | Project 2003 | ||
DB1111 | Access 2003 | ||
DB2222 | SQL Server 2000 Standard | ||
DB3333 | FileMaker Pro 6 | ||
DP1111 | FrameMaker 7.0 | ||
DP2222 | QuarkXPress 6.0 | ||
GR1111 | Photoshop CS | ||
GR2222 | Illustrator CS | ||
|
Edit: | |
Number: | BU1111 |
Type: | Business Office |
Name: | Microsoft Office Professional 2003 |
Supplier: | Microsoft |
Description: |
Microsoft Office Professional Edition 2003 can help you and your organization communicate information with immediacy and impact. New and familiar programs and improved functionality help you build powerful connections between people, information, and business processes.
|
Price: | 419.99 |
Qty: | 20 |
Sale: |
Coding the GridView
Code for the master GridView and its AccessDataSource are shown below. A TemplateField containing <asp:LinkButton> controls both displays item numbers and configures them as command links for selecting products. The CommandName for the LinkButtons is "Select" to tie item numbers to the SelectCommand property of the AccessDataSource for the DetailsView.
<asp:AccessDataSource id="MasterSource" Runat="Server"
DataFile="../Databases/eCommerce.mdb"
SelectCommand="SELECT ItemNumber, ItemName FROM Products ORDER BY ItemNumber"/>
<asp:Label id="EditMSG" EnableViewState="False" ForeColor="Red" Runat="Server"/>
<asp:GridView id="GridView" DataSourceID="MasterSource" Runat="Server"
DataKeyNames="ItemNumber"
AutoGenerateColumns="False"
AllowPaging="True"
PageSize="10"
Width="250"
SelectedIndex="0"
SelectedRowStyle-BackColor="#E9E9E9"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
Style="float:left">
<Columns>
<asp:TemplateField HeaderText="Number" HeaderStyle-Width="50">
<ItemTemplate>
<asp:LinkButton CommandName="Select" Runat="Server">
<%# Eval("ItemNumber") %>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Name" DataField="ItemName"/>
</Columns>
</asp:GridView>
Coding the DetailsView
The DetailsView employs an AccessDataSource whose SelectCommand is linked to the GridView selection through its SelectParameters. The GridView's SelectedValue becomes the @ItemNumber parameter for displaying the chosen record. A second AccessDataSource fills DropDownLists of item types during updating and inserting operations.
<asp:AccessDataSource id="DetailsSource" Runat="Server" DataFile="../Databases/eCommerce.mdb" SelectCommand="SELECT * FROM Products WHERE ItemNumber = @ItemNumber" InsertCommand="INSERT INTO Products (ItemNumber, ItemType, ItemSupplier, ItemName, ItemDescription, ItemPrice, ItemQuantity, ItemSale) VALUES (@ItemNumber, @ItemType, @ItemSupplier, @ItemName, @ItemDescription, @ItemPrice, @ItemQuantity, @ItemSale)" UpdateCommand="UPDATE Products SET ItemType=@ItemType, ItemSupplier=@ItemSupplier, ItemName=@ItemName, ItemDescription=@ItemDescription, ItemPrice=@ItemPrice, ItemQuantity=@ItemQuantity, ItemSale=@ItemSale WHERE ItemNumber=@ItemNumber" > <SelectParameters> <asp:ControlParameter ControlID="GridView" Name="ItemNumber" PropertyName="SelectedValue"/> </SelectParameters> </asp:AccessDataSource> <asp:AccessDataSource id="TypeSource" Runat="Server" DataFile="../Databases/eCommerce.mdb" SelectCommand="SELECT DISTINCT ItemType FROM Products ORDER BY ItemType"/>
Code for the DetailsView is shown below. Editing buttons are supplied through a TemplateField containing Button controls configured as command buttons. Also, a set of delete confirmation buttons appears inside the DetailsView's ItemTemplate.
<asp:DetailsView id="DetailsView" DataSourceID="DetailsSource" Runat="Server" AutoGenerateRows="False" DataKeyNames="ItemNumber" OnItemInserting="Validate_Insert_Data" OnItemInserted="Display_Insert_Msg" OnItemUpdating="Validate_Update_Data" OnItemUpdated="Display_Update_Msg" OnItemDeleting="Confirm_Delete" OnItemCommand="Get_Command" BorderStyle="Outset" BorderWidth="1" CellPadding="3" GridLines="None"> <Fields> <asp:TemplateField HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" HeaderStyle-HorizontalAlign="Right" ItemStyle-VerticalAlign="Top" ItemStyle-BackColor="#E0E0E0" ItemStyle-ForeColor="#FF0000"> <HeaderTemplate> Edit: </HeaderTemplate> <ItemTemplate> <asp:Button CommandName="Edit" Text="Edit" Font-Size="8pt" Width="45" Runat="Server"/> <asp:Button CommandName="New" Text="New" Font-Size="8pt" Width="45" Runat="Server"/> <asp:Button CommandName="Delete" Text="Delete" Font-Size="8pt" Width="45" Runat="Server"/> <asp:Label id="ConfirmDelete" Visible="False" EnableViewState="False" Runat="Server"> <asp:Label Text="Delete this record? " ForeColor="Red" EnableViewState="False" Runat="Server"/> <asp:Button Text="Yes" CommandName="Yes" Font-Size="8pt" Width="30px" Runat="Server"/> <asp:Button Text="No" CommandName="No" Font-Size="8pt" Width="30px" Runat="Server"/> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:Button CommandName="Update" Text="Update" Font-Size="8pt" Width="45" Runat="Server"/> <asp:Button CommandName="Cancel" Text="Cancel" Font-Size="8pt" Width="45" Runat="Server"/> </EditItemTemplate> <InsertItemTemplate> <asp:Button CommandName="Insert" Text="Insert" Font-Size="8pt" Width="45" Runat="Server"/> <asp:Button CommandName="Cancel" Text="Cancel" Font-Size="8pt" Width="45" Runat="Server"/> </InsertItemTemplate> </asp:TemplateField> <asp:BoundField DataField="ItemNumber" ReadOnly="True" HeaderText="Number: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"/> <asp:TemplateField HeaderText="Type: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"> <ItemTemplate> <asp:Label Text='<%# Eval("ItemType") %>' Runat="Server"/> </ItemTemplate> <EditItemTemplate> <asp:DropDownList id="EditType" DataSourceID="TypeSource" Runat="Server" DataTextField="ItemType" DataValueField="ItemType" SelectedValue='<%# Bind("ItemType") %>'/> </EditItemTemplate> </asp:TemplateField> <asp:BoundField DataField="ItemName" HeaderText="Name: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"/> <asp:BoundField DataField="ItemSupplier" HeaderText="Supplier: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"/> <asp:TemplateField HeaderText="Description: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"> <ItemTemplate> <asp:Panel Width="350px" Height="100px" BorderWidth="1px" BorderColor="#C0C0C0" ScrollBars="Auto" Runat="Server"> <asp:Label Text='<%# Eval("ItemDescription") %>' Font-Size="10pt" Runat="Server"/> </asp:Panel> </ItemTemplate> <EditItemTemplate> <asp:TextBox id="EditDescription" Text='<%# Bind("ItemDescription") %>' Runat="Server" TextMode="MultiLine" Rows="5" Width="350px" Font-Name="Arial" Font-Size="9pt"/> </EditItemTemplate> </asp:TemplateField> <asp:BoundField DataField="ItemPrice" HeaderText="Price: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top" DataFormatString="{0:N}"/> <asp:BoundField DataField="ItemQuantity" HeaderText="Qty: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top" DataFormatString="{0:D}"/> <asp:CheckBoxField DataField="ItemSale" HeaderText="Sale: " HeaderStyle-BackColor="#E0E0E0" HeaderStyle-Font-Bold="True" ItemStyle-VerticalAlign="Top"/> </Fields> </asp:DetailsView>
DetailsView Scripting
Scripting for the DetailsView uses similar techniques as before. Click events are trapped by OnItemInserting, OnItemInserted, OnItemUpdating, OnItemUpdated, OnItemDeleting, and OnItemCommand handlers. During inserting and updating, subprograms validate entered data; during deletion, confirmation buttons are presented. All subprograms display appropriate messages about editing status.
Sub Validate_Insert_Data (Src As Object, Args As DetailsViewInsertEventArgs) If Args.Values("ItemNumber") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item number" End If If Args.Values("ItemName") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item name" End If If Args.Values("ItemSupplier") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item supplier" End If If Args.Values("ItemDescription") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item description" End If If Not IsNumeric(Args.Values("ItemPrice")) Then Args.Cancel = True EditMSG.Text = "-- Item price is not numeric" Else If Args.Values("ItemPrice") < 0 Then Args.Cancel = True EditMSG.Text = "-- Item price is out of range" End If End If If Not IsNumeric(Args.Values("ItemQuantity")) Then Args.Cancel = True EditMSG.Text = "-- Item quantity is not numeric" Else If Args.Values("ItemQuantity") < 0 Then Args.Cancel = True EditMSG.Text = "-- Item quantity is out of range" End If End If End Sub Sub Display_Insert_Msg (Src As Object, Args As DetailsViewInsertedEventArgs) EditMSG.Text = "-- Record " & Args.Values("ItemNumber") & " added" GridView.DataBind() End Sub Sub Validate_Update_Data (Src As Object, Args As DetailsViewUpdateEventArgs) If Args.NewValues("ItemName") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item name" End If If Args.NewValues("ItemSupplier") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item supplier" End If If Args.NewValues("ItemDescription") = "" Then Args.Cancel = True EditMSG.Text = "-- Missing item description" End If If Not IsNumeric(Args.NewValues("ItemPrice")) Then Args.Cancel = True EditMSG.Text = "-- Item price is not numeric" Else If Args.NewValues("ItemPrice") < 0 Then Args.Cancel = True EditMSG.Text = "-- Item price is out of range" End If End If If Not IsNumeric(Args.NewValues("ItemQuantity")) Then Args.Cancel = True EditMSG.Text = "-- Item quantity is not numeric" Else If Args.NewValues("ItemQuantity") < 0 Then Args.Cancel = True EditMSG.Text = "-- Item quantity is out of range" End If End If End Sub Sub Display_Update_Msg (Src As Object, Args As DetailsViewUpdatedEventArgs) EditMSG.Text = "-- Record " & Args.Keys("ItemNumber") & " updated" End Sub Sub Confirm_Delete (Src As Object, Args As DetailsViewDeleteEventArgs) Args.Cancel = True Dim ConfirmLabel As Label = DetailsView.Rows(0).FindControl("ConfirmDelete") ConfirmLabel.Visible = True ViewState("ItemNumber") = Args.Keys("ItemNumber") End Sub Sub Get_Command (Src As Object, Args As DetailsViewCommandEventArgs) If Args.CommandName = "Yes" Then DetailsSource1.DeleteCommand = "DELETE FROM Products WHERE ItemNumber = '" & ViewState("ItemNumber") & "'" DetailsSource1.Delete() GridView.DataBind() EditMSG.Text = " Record " & ViewState("ItemNumber") & " deleted" End If End Sub
You will notice a slight difference in coding from previous scripts to locate the ConfirmLabel containing "Yes" and "No" delete confirmation buttons. In coding this technique for a previous FormView, the control's FindControl("id") method is used. For a DetailsView, however, this method's format is different as shown below.
Sub Confirm_Delete (Src As Object, Args As DetailsViewDeleteEventArgs) Args.Cancel = True Dim ConfirmLabel As Label = DetailsView.Rows(0).FindControl("ConfirmDelete") ConfirmLabel.Visible = True ViewState("ItemNumber") = Args.Keys("ItemNumber") End Sub
Whereas a FormView contains a single Row object that is searched for a control, a DetailsView contains multiple Rows, one for each visible row of the control. These rows are indexed beginning with 0, and this index is used to point to the particular row to search to find an enclosed control. In the current DetailsView, the confirmation buttons and their container Label appear in the first row (index = 0). This row index points the FindControl() method to the appropriate row to search for the ConfirmLabel, which is then made visible.
Incidentally, to locate a control on other rows of the DetailsView, or of a GridView, the row index is not known in advance or cannot be anticipated. However, arguments passed to subprograms when events occur on a row include the RowIndex property for that row. This property value then points to the row of interest. For example, to locate a Label with id="MSGLabel" on the same row as an "Update" button that is clicked, the following code can be used.
Sub Find_Label (Src As Object, Args As DetailsViewUpdateEventArgs)
Dim FoundLabel As Label = MyDetailsView.Rows(Args.RowIndex).FindControl("MSGLabel")
End Sub
<asp:DetailsView id="MyDetailsView" ...
OnRowUpdating="Find_Label"
...
Notice in the example GridView that when a new record is added or an existing record is deleted that the GridView is bound again from its AccessDataSource: GridView.DataBind(). This re-binding ensures that the GridView correctly represents the changed contents of the Products table after records are added and deleted.
A FormView can be easily substituted for the above DetailsView. The one from the previous FormView editing tutorial can be used by linking it to the GridView. Slight script changes are needed for subprogram arguments and for locating embedded controls. Still, it is nearly a matter of swapping one control for another.