Master/Detail Display
By pairing an <asp:GridView> control with an
<asp:DetailsView> control you can display a set of master and detail
records from a data source. A master list of records is presented in the GridView. Each record
is accompanied by a link or a button for selecting that row. On the basis of this selection, the
DetailsView displays data fields associated with this same record. An example master/detail
display for the BooksDB.mdb database is shown below. Clicking a
"Select" link in the GridView retrieves and displays fields for the selected record in the
DetailsView.
Book Detail
| ID | DB111 |
| Title | Oracle Database |
| Type | Database |
| Author | K. Loney |
|
Description
|
Get thorough coverage of Oracle Database 10g from the most comprehensive reference available, published by Oracle Press. With in-depth details on all the new features, this powerhouse resource provides an overview of database architecture and Oracle Grid Computing technology, and covers SQL, SQL*Plus, PL/SQL, dynamic PL/SQL, object-oriented features, and Java programming in the Oracle environment. You'll also find valuable database administration and application development techniques, plus an alphabetical reference covering major Oracle commands, keywords, features, and functions, with cross-referencing of topics.
|
| Price | $69.99 |
| Quantity | 10 |
|
Amount
|
$699.90
|
| On Sale | |
Figure 7-29. Display of master/detail records.
Linking Display and Data Source Controls
The GridView and DetailsView controls are linked separately to the same data source through
their respective <asp:AccessDataSource> controls. Special
properties of these controls, however, associate the record chosen from the GridView with the
record displayed in the DetailsView. The general formats for setting up master/detail links among
these controls are shown below.
Figure 7-30. General formats for master/detail display.
The GridView, which displays a set of master records, requires two properties. The AllowGenerateSelectButton="True" property produces a column of
"Select" link buttons (displayed as text links) for selecting individual rows of the GridView.
The DataKeyNames="fieldname" property identifies one or
more data fields in the data source whose values are associated with the link buttons, and which are
used to retrieve matching records for display in the DetailsView. Normally, the
DataKeyNames value is the unique record key field in the data source, although any field
or combination of fields, separated by commas, can be identified. It is important to remember
that a clicked link supplies the GridView's SelectedValue
property, needed for locating the matching record for the DetailsView.
The AccessDataSource associated with the GridView is coded in standard fashion, providing a
path to the DataFile and a SelectCommand to
retrieve a set of records. Partial coding for the GridView and its AccessDataSource to produce
the example display is shown below.
<asp:AccessDataSource id="BookSource1" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books ORDER BY BookID"/>
<asp:GridView id="BookGrid" DataSourceID="BookSource1" Runat="Server"
AutoGenerateSelectButton="True"
DataKeyNames="BookID"
SelectedIndex="0"
SelectedRowStyle-BackColor="#F0F0F0"
...
</asp:GridView>
Listing 7-25. Code to link GridView with AccessDataSource.
The SelectedIndex property of the GridView identifies a
row that is selected by clicking the "Select" button. When the GridView is initially displayed,
no rows are selected, even though the accompanying DetailsView displays, by default, the first
record from the same data source. In this example, selected rows in the GridView are "highlighted"
with a shaded background. Therefore, the SelectedIndex property is
initially set to point to this first row (row index = 0) so that it will be highlighted when
the GridView is first displayed. Without this special row formatting, the
SelectedIndex property is not required.
A separate AccessDataSource is associated with the DetailsView. It requires
DataFile and SelectCommand properties to link to the same data
source used for the GridView. Also, it requires additional properties and controls in order
to display details for the record selected from the GridView. Partial coding for the DetailsView
and its AccessDataSource are shown below.
<asp:AccessDataSource id="BookSource2" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books WHERE BookID = @BookID">
<SelectParameters>
<asp:ControlParameter Name="BookID" ControlID="BookGrid"
PropertyName="SelectedValue"/>
</SelectParameters>
</asp:AccessDataSource>
<asp:DetailsView id="BookView" DataSourceID="BookSource2" Runat="Server"
...
</asp:DetailsView>
Listing 7-26. Code to link DetailsView with AccessDataSource.
Note that the AccessDataSource is coded as separate opening and closing tags inside of which
are tags to associate a displayed record with the record selected from the GridView.
Parameters for SelectCommands
In order to retrieve the record matching the one selected in the GridView, the AccessDataSource
for the DetailsView must issue a SelectCommand to retrieve the record
matching the one selected in the GridView. In this example, the matching record is one with a
BookID value matching the BookID selected
in the GridView.
The SelectCommand issued through the AccessDataSource for the
DetailsView cannot know in advance which record to select. It depends on which record is selected
in the GridView. Therefore, a parameterized SelectCommand is
used.
SelectCommand="SELECT * FROM Books WHERE BookID = @BookID">
Listing 7-27. Parameterized SelectCommand for AccessDataSource.
The parameter @BookID is a placeholder for a value. Parameters
are programmer-supplied names prefixed with the "@" character. The
value of a parameter comes from a source identified in an
<asp:ControlParameter> control coded inside a
<SelectParameters> tag enclosed in the AccessDataSource.
<SelectParameters>
<asp:ControlParameter Name="BookID" ControlID="BookGrid"
PropertyName="SelectedValue"/>
</SelectParameters>
Listing 7-28. Control parameters for a SelectCommand for AccessDataSource for DetailsView.
Name="BookID" in the ControlParameter points to the
@BookID parameter of the same name in the
SelectCommand, indicating that this ControlParameter supplies the replacement value for the
SelectCommand parameter. A ControlID
identifies the control which is the source of this value, and PropertyName
gives the control's property setting whose value becomes the replacement value for the
parameter. In this example, ControlID="BookGrid" identifies the
GridView control whose SelectedValue supplies the value
for the parameter. That is, the selected BookID from the GridView
supplies the value for the @BookID parameter of the
SelectCommand for the DetailsView.
Filters for SelectCommands
A slightly different tactic can be taken to match the DetailsView display with a book
selected in the GridView. The DetailsView's AccessDataSource also can be coded as follows.
<asp:AccessDataSource id="BookSource2" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books"
FilterExpression="BookID = '@BookID'">
<FilterParameters>
<asp:ControlParameter Name="BookID" ControlID="BookGrid"
PropertyName="SelectedValue"/>
</FilterParameters>
</asp:AccessDataSource>
<asp:DetailsView id="BookView" DataSourceID="BookSource2" Runat="Server"
...
</asp:DetailsView>
Listing 7-29. Filtering a SelectCommand for AccessDataSource.
A FilterExpression for a SelectCommand
is used to compose a WHERE clause for the SELECT
statement. The expression contains a parameterized value (in single quotes for string data) that
is retrieved from an <asp:ControlParameter> coded in the
<FilterParameters> section of the data source control.
A ControlParameter identifies a data value from a different control for use in the current control
for filtering SelectCommands.
In the present example, the FilterExpression identifies
"BookID='@BookID'" as the filter, supplying the parameter @BookID whose replacement value is used to uniquely identify the record
to be retrieved. This parameter value is linked to a matching name in a
<asp:ControlParameter> control, namely Name="BookID" in
the current example. Thus, the BookID value for the record selected
in the GridView (the PropertyName="SelectedValue" property of the
ControlID="BookGrid" control) becomes the value used in a WHERE clause to filter the SELECT statement
in the SelectCommand for the DetailsView, thereby retrieving
the matching record.
Whether you use SelectParameters to supply a value for a
SELECT statement with a WHERE clause (as in the first
example), or you use FilterParameters to compose a SELECT statement
without a WHERE clause (as in the second example), is mostly a
matter of programmer preference.
Master/Detail Coding
Complete coding for the master/detail display at the top of this page is shown below.
Much of the coding is the same as for individual GridView and DetailsView controls described
in previous tutorials. One of the styling differences is in setting the background color of
selected rows in the GridView with the SelectedRowStyle-BackColor
property. Also, the GridView has a Style="float:left; margin-right:20px"
CSS style settings so that both controls appear side by side.
<!-- Master Coding -->
<asp:AccessDataSource id="BookSource1" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books ORDER BY BookID"/>
<asp:GridView id="BookGrid" DataSourceID="BookSource1" Runat="Server"
AutoGenerateSelectButton="True"
DataKeyNames="BookID"
SelectedIndex="0"
AutoGenerateColumns="False"
AllowPaging="True"
PageSize="11"
CellPadding="1"
Caption="<b>Book Master</b>"
CaptionAlign="Left"
HeaderStyle-BackColor="#E0E0E0"
SelectedRowStyle-BackColor="#F0F0F0"
Style="float:left; margin-right:20px"
Width="110">
<Columns>
<asp:BoundField
DataField="BookID"
HeaderText="ID"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
</Columns>
</asp:GridView>
<!-- Detail Coding -->
<asp:AccessDataSource id="BookSource2" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books WHERE BookID = @BookID">
<SelectParameters>
<asp:ControlParameter Name="BookID" ControlId="BookGrid"
PropertyName="SelectedValue"/>
</SelectParameters>
</asp:AccessDataSource>
<asp:DetailsView id="BookView" DataSourceID="BookSource2" Runat="Server"
AutoGenerateRows="False"
BorderWidth="1"
CellPadding="1"
GridLines="None"
Caption="<b>Book Detail</b>"
CaptionAlign="Left"
Width="385"
RowStyle-VerticalAlign="Top">
<Fields>
<asp:BoundField
DataField="BookID"
HeaderText="ID"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
<asp:BoundField
DataField="BookTitle"
HeaderText="Title"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
<asp:BoundField
DataField="BookType"
HeaderText="Type"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
<asp:BoundField
DataField="BookAuthor"
HeaderText="Author"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
<asp:TemplateField
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="10pt">
<HeaderTemplate>
Description
</HeaderTemplate>
<ItemTemplate>
<asp:Image Runat="Server"
Style="float:left"
ImageUrl='<%# "../BookPictures/" & Eval("BookID") & ".jpg" %>'/>
<asp:Label Runat="Server"
Style="overflow:auto; width:195px; height:105px"
Text='<%# Eval("BookDescription") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField
DataField="BookPrice"
HeaderText="Price"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"
HtmlEncode="False"
DataFormatString="{0:C}"/>
<asp:BoundField
DataField="BookQty"
HeaderText="Quantity"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"
HtmlEncode="False"
DataFormatString="{0:D}"/>
<asp:TemplateField
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt">
<HeaderTemplate>
Amount
</HeaderTemplate>
<ItemTemplate>
<asp:Label Runat="Server"
Text='<%# FormatCurrency(Eval("BookPrice") * Eval("BookQty")) %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:CheckBoxField
DataField="BookSale"
HeaderText="On Sale"
HeaderStyle-BackColor="#E0E0E0"
HeaderStyle-Font-Bold="True"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
</Fields>
</asp:DetailsView>
Listing 7-30. Code for master/detail display of GridView and DetailsView.
Select Button Types
When AutoGenerateSelectButton="True" is specified for a GridView,
a text "Select" button is created for each row of records. This is the default
"Link" style for the buttons. You can, instead, choose a different visual presentation of
buttons by coding AutoGenerateSelectButton="False" (or by not coding the
property setting) and creating your own button column.
A column of buttons is added to the GridView by creating an
<asp:ButtonField> control. The properties set for this control for use as a
"Select" button are shown below.
Figure 7-31. General format for <asp:ButtonField> control used as selection link.
The ButtonType property sets the button type. Use
"Button" for a standard button, along with a
Text value to serve as the label for the button. Use "Image"
to indicate a graphic button, along with an ImageUrl property to
give the URL for the image. In both cases, a CommandName="Select"
property must be coded for the button to issue the necessary Select command
so that post-back to the server retrieves the appropriate record for viewing in the DetailsView
display.
It is not necessary to use the special <asp:ButtonField> control
to supply a standard button for making selections. You can use a TemplateField enclosing a
standard <asp:Button> control. Just remember to set the
CommandName property of the button to "Select".
The following output is a duplicate of the previous master/detail application in which a
button replaces the text "Select" links for displaying associated detail records. Here, a
standard Button (rather than a ButtonField) is used to trigger selections.
Book Detail
| ID | DB111 |
| Title | Oracle Database |
| Type | Database |
| Author | K. Loney |
|
Description
|
Get thorough coverage of Oracle Database 10g from the most comprehensive reference available, published by Oracle Press. With in-depth details on all the new features, this powerhouse resource provides an overview of database architecture and Oracle Grid Computing technology, and covers SQL, SQL*Plus, PL/SQL, dynamic PL/SQL, object-oriented features, and Java programming in the Oracle environment. You'll also find valuable database administration and application development techniques, plus an alphabetical reference covering major Oracle commands, keywords, features, and functions, with cross-referencing of topics.
|
| Price | $69.99 |
| Quantity | 10 |
|
Amount
|
$699.90
|
| On Sale | |
Figure 7-32. Display of master/detail records.
The following partial code shows the recoded sections of the master/detail application to create
a column of Buttons for display of detail records.
<asp:GridView id="BookGrid" DataSourceID="BookSource1" Runat="Server"
AutoGenerateColumns="False"
AutoGenerateSelectButtons="False"
DataKeyNames="BookID"
SelectedIndex="0"
...>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button Text="Select" CommandName="Select"
Font-Size="7pt" Runat="Server"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField
DataField="BookID"
HeaderText="ID"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="11pt"/>
</Columns>
</asp:GridView>
Listing 7-31. Code for Button column of GridView to selecte records for DetailsView display.
Master/Detail Layout with FormView Control
A FormView control can be used in place of a DetailsView for setting up master/detail display
arrangments. The following example uses a GridView for displaying and selecting all books from
the Books table; a FormView is used for drill-down display of a
selected record.
Book Master
| ID | Title |
|
DB111
| Oracle Database |
|
DB222
| Databases in Depth |
|
DB333
| Database Processing |
|
DB444
| Access Database Design |
|
DB555
| SQL Server 2005 |
|
GR111
| Adobe Photoshop CS2 |
|
GR222
| Learning Web Design |
|
GR333
| Macromedia Flash Professional |
|
GR444
| Digital Photographer Handbook |
|
GR555
| Creating Motion Graphics |
|
Figure 7-33. Display of master/detail records with FormView.
A slightly different technique is used for selecting records from the GridView for display
in the FormView. In this example, a separate button column is not used to display selection buttons;
rather, a TemplateField containing an <asp:LinkButton> control
both displays BookIDs and configures them as command links for selecting
books. Changes to previous GridView coding include setting
AutoGenerateSelectButton="False" (the default setting which also can be effected by not
coding the property) and including the TemplateField. The CommandName
for the LinkButton must be "Select" to tie the
BookID to the SelectCommand property of the AccessDataSource for
the FormView. An advantage of using a TemplateField is that it does not produce the extra column
of links displayed when using a ButtonField or when links are automatically produced with AutoGenerateSelectButtons="True".
<asp:AccessDataSource id="BookSource1" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books ORDER BY BookID"/>
<asp:GridView id="BookGrid" DataSourceID="BookSource1" Runat="Server"
AutoGenerateSelectButton="False"
DataKeyNames="BookID"
SelectedIndex="0"
AutoGenerateColumns="False"
AllowPaging="True"
PageSize="10"
CellPadding="1"
Caption="<b>Book Master</b>"
CaptionAlign="Left"
HeaderStyle-BackColor="#E0E0E0"
SelectedRowStyle-BackColor="#F0F0F0"
Style="float:left; margin-right:10px"
Width="220">
<Columns>
<asp:TemplateField
HeaderText="ID"
HeaderStyle-Width="40px"
HeaderStyle-Font-Size="10pt"
ItemStyle-Font-Size="10pt">
<ItemTemplate>
<asp:LinkButton Runat="Server"
Text='<%# Eval("BookID") %>'
CommandName="Select"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField
DataField="BookTitle"
HeaderText="Title"
HeaderStyle-Font-Size="11pt"
ItemStyle-Font-Size="10pt"/>
</Columns>
</asp:GridView>
Listing 7-32. Code for GridView template column for master/detail link buttons.
Code for the FormView is shown below. Its coding is similar to previous FormView displays except
that its AccessDataSource is tied to record selections made from the GridView.
<asp:AccessDataSource id="BookSource2" Runat="Server"
DataFile="../Databases/BooksDB.mdb"
SelectCommand="SELECT * FROM Books Where BookID = @BookID">
<SelectParameters>
<asp:ControlParameter Name="BookID" ControlId="BookGrid"
PropertyName="SelectedValue"/>
</SelectParameters>
</asp:AccessDataSource>
<asp:FormView id="BookForm" DataSourceID="BookSource2" Runat="Server"
AllowPaging="True"
GridLines="None"
Width="280"
HeaderStyle-Font-Bold="True"
RowStyle-Font-Size="10pt">
<HeaderTemplate>
Book Detail
</HeaderTemplate>
<ItemTemplate>
<asp:Image Style="float:left; margin-right:10px" Runat="Server"
ImageUrl='<%# "../BookPictures/" & Eval("BookID") & ".jpg" %>'/>
<asp:Label Text='<%# Eval("BookType") & " - " %>' Runat="Server"/>
<asp:Label Text='<%# Eval("BookID") %>' Runat="Server"/><br/>
<asp:Label Text='<%# Eval("BookTitle") %>' Font-Bold="True" Runat="Server"/><br/>
<asp:Label Text='<%# Eval("BookAuthor") %>' Runat="Server"/><br/>
<asp:Label Text='<%# Get_Sale_Price(Eval("BookPrice"), Eval("BookSale")) %>' Runat="Server"/><br/>
<asp:Label Text='<%# String.Format("{0:D}", Eval("BookQty")) %>' Runat="Server"/>
<asp:CheckBox Checked='<%# Eval("BookSale") %>' Enabled="False" Text="On Sale" Runat="Server"/><br/>
<br clear="left"><br/>
<asp:Label Runat="Server"
Width="280" Height="103" Style="overflow:auto"
Text='<%# Eval("BookDescription") %>'/><br/>
</ItemTemplate>
</asp:FormView>
Listing 7-33. Code for FormView used for master/detail display.
As was done in a previous FormView, display of book prices results from a function call
to determine if a discounted price should be displayed. The same Get_Sale_Price
function is used in this application.
<SCRIPT Runat="Server">
Function Get_Sale_Price (Price As Decimal, Sale As Boolean)
If Sale = True Then
Price = Price - (.10 * Price)
Return String.Format("<span style=""color:red"">{0:C} " & _
"<b>Special</b></span>", Price)
Else
Return String.Format("{0:C}", Price)
End If
End Function
</SCRIPT>
Listing 7-34. Code for Get_Sale_Price function called from FormView.