Chapter 12. Using the DetailsView and FormView Controls

<feature><title>In this Chapter</title> <objective>

Using the DetailsView Control

</objective>
<objective>

Using the FormView Control

</objective>
<objective>

Summary

</objective>
</feature>

The DetailsView and FormView controls, the subject of this chapter, enable you to work with a single data item at a time. Both controls enable you to display, edit, insert, and delete data items such as database records. Furthermore, both controls enable you to page forward and backward through a set of data items.

The difference between the two controls concerns the user interface that the controls render. The DetailsView control always renders each field in a separate HTML table row. The FormView control, on the other hand, uses a template that enables you to completely customize the user interface rendered by the control.

Using the DetailsView Control

In this section, you learn how to use the DetailsView control when working with database records. In particular, you learn how to display, page, edit, insert, and delete database records with the DetailsView. You also learn how to format the appearance of the DetailsView control.

Displaying Data with the DetailsView Control

A DetailsView control renders an HTML table that displays the contents of a single database record. The DetailsView supports both declarative and programmatic databinding.

For example, the page in Listing 12.1 displays a record from the Movies database table, using declarative databinding (see Figure 12.1).

Displaying a movie record.

Figure 12.1. Displaying a movie record.

Example 12.1. ShowDetailsView.aspx

<%@ Page Language="VB" %>
<!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 DetailsView</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        Runat="server" />

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies
            WHERE Id=1"
        Runat="server" />

    </div>
    </form>
</body>
</html>

In Listing 12.1, the SQL Select statement associated with the SqlDataSource control retrieves the first movie from the Movies database table. The DetailsView control is bound to the SqlDataSource control through its DataSourceID property.

You also can bind a DetailsView control programmatically to a data source. The page in Listing 12.2 contains a DetailsView that is bound to a collection of employees.

Example 12.2. ShowEmployee.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Collections.Generic" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    ''' <summary>
    ''' Represents an employee
    ''' </summary>
    Public Class Employee
        Public _firstName As String
        Public _lastName As String
        Public _retired As Boolean

        Public ReadOnly Property FirstName() As String
            Get
                Return _firstName
            End Get
        End Property

        Public ReadOnly Property LastName() As String
            Get
                Return _lastName
            End Get
        End Property

        Public ReadOnly Property Retired() As Boolean
            Get
                Return _retired
            End Get
        End Property

        Public Sub New(ByVal firstName As String, ByVal lastName As String, ByVal retired As Boolean)
            _firstName = firstName
            _lastName = lastName
            _retired = retired
        End Sub
    End Class

    ''' <summary>
    ''' Load employees into DetailsView
    ''' </summary>
    Private Sub Page_Load()
        ' Create employees collection with one employee
        Dim NewEmployee As New Employee("Steve", "Walther", False)
        Dim employees As New List(Of Employee)()
        employees.Add(NewEmployee)

        ' Bind employees to DetailsView
        dtlMovies.DataSource = employees
        dtlMovies.DataBind()
    End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Show Employee</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

In Listing 12.2, an Employee class is defined, which contains properties for the employee first name, last name, and retirement status. In the Page_Load() method, a new employee is created and added to a generic collection. This collection is bound to the DetailsView control.

Using Fields with the DetailsView Control

If you need more control over the appearance of the DetailsView, including the particular order in which columns are displayed, then you can use fields with the DetailsView control. The DetailsView control supports exactly the same fields as the GridView control:

  • BoundField—. Enables you to display the value of a data item as text.

  • CheckBoxField—. Enables you to display the value of a data item as a check box.

  • CommandField—. Enables you to display links for editing, deleting, and selecting rows.

  • ButtonField—. Enables you to display the value of a data item as a button (image button, link button, or push button).

  • HyperLinkField—. Enables you to display the value of a data item as a link.

  • ImageField—. Enables you to display the value of a data item as an image.

  • TemplateField—. Enables you to customize the appearance of a data item.

Note

Another option is to create custom fields for the DetailsView control. You can create custom fields that work with the DetailsView control in exactly the same way as you create custom fields that work with the GridView control. Custom fields for the GridView control are discussed in the final section of Chapter 11, “Using the GridView Control.”

The page in Listing 12.3 contains a DetailsView control that contains three BoundFields. The BoundFields display the values of the Title, Director, and BoxOfficeTotals database columns (see Figure 12.2).

Example 12.3. ShowFields.aspx

<%@ Page Language="VB" %>
<!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 Fields</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AutoGenerateRows="false"
        Runat="server">
        <Fields>
        <asp:BoundField
            DataField="Title"
            HeaderText="Movie Title:" />
        <asp:BoundField
            DataField="Director"
            HeaderText="Movie Director:" />
        <asp:BoundField
            DataField="BoxOfficeTotals"
            DataFormatString="{0:c}"
            HtmlEncode="false"
            HeaderText="Box Office Totals:" />
        </Fields>
    </asp:DetailsView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,BoxOfficeTotals FROM Movies
            WHERE Id=1"
        Runat="server" />

    </div>
    </form>
</body>
</html>
Using BoundFields with the DetailsView control.

Figure 12.2. Using BoundFields with the DetailsView control.

Notice that the DetailsView control has an AutoGenerateRows property that has the value False. When you specify fields for a DetailsView control, you’ll want to include this property so that the fields do not appear more than once.

Each of the BoundFields in Listing 12.3 includes a HeaderText attribute that is used to specify the label for the field. In addition, the BoundField associated with the BoxOfficeTotals column includes a DataFormatString property that is used to format the value of the column as a currency amount.

Warning

Make sure that you disable HTML encoding by setting the HtmlEncode property to the value False when you use the DataFormatString property. Otherwise the format string is ignored.

Displaying Empty Data with the DetailsView Control

The DetailsView control includes two properties that you can use to display a message when no results are returned from its data source. You can use the EmptyDataText property to display an HTML string, or the EmptyDataTemplate property to display more complicated content.

For example, the SqlDataSource in Listing 12.4 does not return a record because no record in the Movies database table has an ID of –1.

Example 12.4. ShowEmptyDataText.aspx

<%@ Page Language="VB" %>
<!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 Empty Data Text</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        EmptyDataText="<b>No Matching Record!</b>"
        Runat="server" />

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies
            WHERE Id=-1"
        Runat="server" />

    </div>
    </form>
</body>
</html>

When you open the page in Listing 12.4, the contents of the EmptyDataText property are displayed.

If you need to display more complicated content when no results are returned, such as ASP.NET controls, then you can specify an EmptyDataTemplate. The page in Listing 12.5 illustrates how you can use the EmptyDataTemplate to display complicated HTML content (see Figure 12.3).

Example 12.5. ShowEmptyDataTemplate.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
        .noMatch
        {
            background-color:#ffff66;
            padding:10px;
            font-family:Arial,Sans-Serif;
        }
        .noMatch h1
        {
            color:red;
            font-size:16px;
            font-weight:bold;
        }
    </style>
    <title>Show Empty Data Template</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        Runat="server">
        <EmptyDataTemplate>
        <div class="noMatch">
            <h1>No Matching Results!</h1>
            Please select a different record.
        </div>
        </EmptyDataTemplate>
    </asp:DetailsView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies
            WHERE Id=-1"
        Runat="server" />

    </div>
    </form>
</body>
</html>
Displaying content when no results are returned.

Figure 12.3. Displaying content when no results are returned.

Paging through Data with the DetailsView Control

You can use the DetailsView to page through a set of database records by enabling the DetailsView control’s AllowPaging property. The page in Listing 12.6 illustrates how you can page through the records in the Movies database table (see Figure 12.4).

Example 12.6. ShowPaging.aspx

<%@ Page Language="VB" %>
<!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 Paging</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        Runat="server" />

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>
Paging through records with the DetailsView control.

Figure 12.4. Paging through records with the DetailsView control.

Warning

In this section, you learn how to take advantage of user interface paging when paging through records with the DetailsView control. Although user interface paging is convenient, it is not efficient. When working with large sets of records, you should use data source paging. This option is described in Chapter 15, “Using the ObjectDataSource Control.”

Paging with AJAX

By default, when you page through records with the DetailsView control, the page is posted back to the server each and every time you click a page number. As an alternative, you can take advantage of AJAX to page through records. When you take advantage of AJAX, only the DetailsView control and not the entire page is updated when you navigate to a new page of records.

Note

AJAX (Asynchronous JavaScript and XML) enables you to retrieve content from a web server without reloading the page. AJAX works with all modern browsers including Microsoft Internet Explorer 6.0, Firefox 1.0, and Opera 8.0.

The page in Listing 12.7 illustrates how you can use AJAX with the DetailsView control.

Example 12.7. ShowAJAX.aspx

<%@ Page Language="VB" %>
<!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 Paging</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <%= DateTime.Now %>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        EnablePagingCallbacks="true"
        Runat="server" />

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that the DetailsView control in Listing 12.7 includes an EnablePagingCallbacks property which has the value True. This property enables AJAX while paging with the DetailsView.

Furthermore, notice that the page in Listing 12.7 displays the current time. The time is not updated when you navigate to a new page of records. The time is not updated because the entire page is not updated. When you navigate to a new page, only the contents of the DetailsView are updated.

Customizing the Paging Interface

You can customize the appearance of the paging interface by modifying the PagerSettings property. For example, the DetailsView control in Listing 12.8 displays first, previous, next, and last links instead of page numbers (see Figure 12.5).

Using PagerSettings to customize the paging interface.

Figure 12.5. Using PagerSettings to customize the paging interface.

Example 12.8. ShowPagerSettings.aspx

<%@ Page Language="VB" %>
<!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 Pager Settings</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        Runat="server">
        <PagerSettings
            Mode="NextPreviousFirstLast"
            FirstPageText="[First Movie]"
            LastPageText="[Last Movie]"
            NextPageText="[Next Movie]"
            PreviousPageText="[Previous Movie]" />
    </asp:DetailsView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

The PagerSettings class supports the following properties:

  • FirstPageImageUrl—. Enables you to display an image for the first page link.

  • FirstPageText—. Enables you to specify the text for the first page link.

  • LastPageImageUrl—. Enables you to display an image for the last page link.

  • LastPageText—. Enables you to specify the text for the last page link.

  • Mode—. Enables you to select a display mode for the pager user interface. Possible values are NextPrevious, NextPreviousFirstLast, Numeric, and NumericFirstLast.

  • NextPageImageUrl—. Enables you to specify the text for the next page link.

  • NextPageText—. Enables you to specify the text for the next page link.

  • PageButtonCount—. Enables you to specify the number of page number links to display.

  • Position—. Enables you to specify the position of the paging user interface. Possible values are Bottom, Top, TopAndBottom.

  • PreviousPageImageUrl—. Enables you to display an image for the previous page link.

  • PreviousPageText—. Enables you to specify the text for the previous page link.

  • Visible—. Enables you to hide the paging user interface.

If you need to customize the paging interface completely, then you can use a template. For example, the page in Listing 12.9 displays a list of page numbers in a drop-down list control (see Figure 12.6).

Using a PagerTemplate to customize the paging interface.

Figure 12.6. Using a PagerTemplate to customize the paging interface.

Example 12.9. ShowPagerTemplate.aspx

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Protected Sub dtlMovies_DataBound(ByVal sender As Object, ByVal e As EventArgs)
        Dim ddlPager As DropDownList = CType(dtlMovies.BottomPagerRow.Cells(0).FindControl("ddlPager"), DropDownList)
        For i As Integer = 0 To dtlMovies.PageCount - 1
            Dim item As New ListItem(String.Format("Record {0}", i + 1), i.ToString())
            If dtlMovies.PageIndex = i Then
                item.Selected = True
            End If
            ddlPager.Items.Add(item)
        Next
    End Sub

    Protected Sub btnPage_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim ddlPager As DropDownList = CType(dtlMovies.BottomPagerRow.Cells(0).FindControl("ddlPager"), DropDownList)
        dtlMovies.PageIndex = Int32.Parse(ddlPager.SelectedValue)
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Show Pager Template</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        OnDataBound="dtlMovies_DataBound"
        Runat="server">
        <PagerTemplate>
            <asp:DropDownList
                id="ddlPager"
                Runat="server" />
            <asp:Button
                id="btnPage"
                Text="Select"
                Runat="server" OnClick="btnPage_Click" />
        </PagerTemplate>
    </asp:DetailsView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

After you open the page in Listing 12.9, you can select a record from the DropDownList control and navigate to the record by clicking the Button control.

Updating Data with the DetailsView Control

You can use the DetailsView control to update existing database records. In order 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).

Editing a record with the DetailsView control.

Figure 12.7. Editing a record with the DetailsView control.

Example 12.10. ShowUpdate.aspx

<%@ Page Language="VB" %>
<!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>

    <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.

Notice that 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.

Notice that 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, then 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 the GridView, you can edit the record with the DetailsView control (see Figure 12.8).

Displaying a Master/Detail form with the DetailsView control.

Figure 12.8. Displaying a Master/Detail form with the DetailsView control.

Example 12.11. MasterDetailEdit.aspx

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Private Sub Page_Load()
        If Not Page.IsPostBack Then
            grdMovies.SelectedIndex = 0
        End If
    End Sub

    Protected Sub dtlMovies_ItemUpdated(ByVal sender As Object, ByVal e As DetailsViewUpdatedEventArgs)
        grdMovies.DataBind()
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {
            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"
        OnItemUpdated="dtlMovies_ItemUpdated"
        Runat="server" />

    <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>

Notice that the DetailsView control includes a DefaultMode property that is set to the value Edit. When you select a record, the record is displayed by the 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 validation, then 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).

Using a template when editing with the DetailsView control.

Figure 12.9. Using a template when editing with the DetailsView control.

Example 12.12. TemplateEdit.aspx

<%@ Page Language="VB" %>
<!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">
        <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"
        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, then a validation error is displayed. Also, if you enter anything other than a currency amount for the BoxOfficeTotals column, a validation error message is displayed.

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 two-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, then 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, then the SqlDataSource tracks both the original and modified versions of each column.

For example, the page in Listing 12.13 doesn’t allow a user to update a record when the original record has been modified after the user has opened the page.

Example 12.13. Concurrency.aspx

<%@ Page Language="VB" %>
<!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>Concurrency</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <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 Title=@original_Title
            AND Director=@original_Director
            AND InTheaters=@InTheaters
            AND Id=@original_Id"
        ConflictDetection="CompareAllValues"
        OldValuesParameterFormatString="original_{0}"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice the contents of the 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, then the record is not updated.

The SqlDataSource has both its ConflictDetection and OldValuesParameterFormatString properties set. The OldValuesParameterFormatString specifies the prefix added to the parameters that represent the original field values.

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.

Example 12.14. ShowInsert.aspx

<%@ Page Language="VB" %>
<!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,@InTheaters)"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that the DetailsView control in Listing 12.14 includes an AutoGenerateInsertButton property that has the value True. This property automatically generates the user interface for inserting a new record.

After you open the page in Listing 12.14, you can click the New button to display a form for inserting a new record. When you click the Insert button, the SQL command represented by the SqlDataSource control’s InsertCommand property is executed.

If you want the DetailsView control to display an insert form by default, then you can assign the value Insert to the DetailsView control’s DefaultMode property. This approach is illustrated by the page in Listing 12.15 (see Figure 12.10).

Inserting a record with the DetailsView control.

Figure 12.10. Inserting a record with the DetailsView control.

Example 12.15. ShowInsertMode.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
        html
        {
            background-color:silver;
            font:14px Arial,Sans-Serif;
        }
        td,th
        {
            padding:10px;
        }
        #divDisplay
        {
            border:solid 1px black;
            width:400px;
            padding:15px;
            background-color:#eeeeee;
        }
        #divInsert
        {
            display:none;
            border:solid 1px black;
            width:400px;
            position:absolute;
            top:30px;
            left:100px;
            padding:10px;
            background-color:white;
        }

    </style>
    <script type="text/javascript">
        function showInsert()
        {
            var divInsert = document.getElementById('divInsert'),
            divInsert.style.display = 'block';
        }
    </script>
    <title>Show Insert Mode</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="divDisplay">
    <asp:GridView
        id="grdMovies"
        DataSourceID="srcMovies"
        Runat="server" />
    <br />
    <a href="JavaScript:showInsert();">Insert Movie</a>
    </div>

    <div id="divInsert">
    <h1>Insert Movie</h1>
    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AutoGenerateInsertButton="true"
        AutoGenerateRows="false"
        DefaultMode="Insert"
        Runat="server">
        <Fields>
        <asp:BoundField
            DataField="Title"
            HeaderText="Title:" />
        <asp:BoundField
            DataField="Director"
            HeaderText="Director:" />
        <asp:CheckBoxField
            DataField="InTheaters"
            HeaderText="In Theaters:" />
        </Fields>
    </asp:DetailsView>
    </div>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Title,Director,InTheaters FROM Movies"
        InsertCommand="INSERT Movies (Title,Director,InTheaters)
            VALUES (@Title,@Director,@InTheaters)"
        Runat="server" />

    </form>
</body>
</html>

The page in Listing 12.15 contains both a GridView and DetailsView control. The DetailsView control is hidden until you click the Insert Movie link. This link executes a JavaScript function named ShowInsert(), which displays the DetailsView control.

Note

You can hide a column when a DetailsView control is in Insert mode with the BoundField control’s InsertVisible property. This property is useful, for example, when you want to prevent users from inserting a value for an identity column.

Deleting Data with the DetailsView Control

You can delete records with the DetailsView control by enabling its AutoGenerateDeleteButton property. The page in Listing 12.16 enables you to both insert and delete records in the Movies database table.

Example 12.16. ShowDelete.aspx

<%@ Page Language="VB" %>
<!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 Delete</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        AllowPaging="true"
        DataSourceID="srcMovies"
        DataKeyNames="Id"
        AutoGenerateInsertButton="true"
        AutoGenerateDeleteButton="true"
        AutoGenerateRows="false"
        Runat="server">
        <Fields>
        <asp:BoundField
            DataField="Id"
            HeaderText="ID:"
            InsertVisible="false" />
        <asp:BoundField
            DataField="Title"
            HeaderText="Title:" />
        <asp:BoundField
            DataField="Director"
            HeaderText="Director:" />
        <asp:CheckBoxField
            DataField="InTheaters"
            HeaderText="In Theaters:" />
        </Fields>
    </asp:DetailsView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies"
        InsertCommand="INSERT Movies (Title,Director,InTheaters)
            VALUES (@Title,@Director,@InTheaters)"
        DeleteCommand="DELETE Movies WHERE id=@Id"
        Runat="server" />

    </div>
    </form>
</body>
</html>

When deleting records, you need to supply a value for the DetailsView control’s DataKeyNames property. Notice that a parameter named @Id is used to represent the value of the ID column in the DeleteCommand property.

Working with DetailsView Control Events

The DetailsView control supports the following events:

  • DataBinding—. Raised immediately before the DetailsView control is bound to its data source.

  • DataBound—. Raised immediately after the DetailsView control is bound to its data source.

  • ItemCommand—. Raised when any control contained in the DetailsView raises an event (for example, when you click a button rendered by a ButtonField).

  • ItemCreated—. Raised when a DetailsView renders a data item.

  • ItemDeleting—. Raised immediately before a data item is deleted.

  • ItemDeleted—. Raised immediately after a data item is deleted.

  • ItemInserting—. Raised immediately before a data item is inserted.

  • ItemInserted—. Raised immediately after a data item is inserted.

  • ItemUpdating—. Raised immediately before a data item is updated.

  • ItemUpdated—. Raised immediately after a data item is updated.

  • ModeChanging—. Raised immediately before the DetailsView control’s mode is changed.

  • ModeChanged—. Raised immediately after the DetailsView control’s mode is changed.

  • PageIndexChanging—. Raised immediately before the current page is changed.

  • PageIndexChanged—. Raised immediately after the current page is changed.

Notice that several of these events reflect similar events exposed by the DataSource controls. For example, the SqlDataSource control includes Inserting and Inserted events, which mirror the DetailsView control’s ItemInserting and ItemInserted events.

The page in Listing 12.17 demonstrates how to use the ItemInserted event to handle any errors which might be raised when inserting a new record into a database table (see Figure 12.11).

Handling database insert errors.

Figure 12.11. Handling database insert errors.

Example 12.17. InsertErrors.aspx

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Protected Sub dtlMovies_ItemInserted(ByVal sender As Object, ByVal e As DetailsViewInsertedEventArgs)
        If Not IsNothing(e.Exception) Then
            e.ExceptionHandled = True
            e.KeepInInsertMode = True
            lblError.Visible = True
        End If
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .error
        {
            color:red;
            font:bold 14px Arial,Sans-Serif;
        }
    </style>
    <title>Insert Errors</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:Label
        id="lblError"
        Text="Could not insert record"
        Visible="false"
        EnableViewState="false"
        CssClass="error"
        Runat="server" />

    <asp:DetailsView
        id="dtlMovies"
        AllowPaging="true"
        DataSourceID="srcMovies"
        AutoGenerateInsertButton="true"
        OnItemInserted="dtlMovies_ItemInserted"
        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,@InTheaters)"
        Runat="server" />

    </div>
    </form>
</body>
</html>

If you attempt to insert a record without providing values for the Title or Director column, then the error message contained in the Label control is displayed.

When you insert a record, the DetailsView control raises the ItemInserted event. The second parameter passed to the event handler for this method contains a property that exposes any exceptions raised when inserting the record. In Listing 12.17, if there is an exception, then the exception is suppressed with the ExceptionHandled property. Furthermore, the KeepInInsertMode property prevents the DetailsView from automatically switching out of Insert mode.

Formatting the DetailsView Control

The DetailsView control includes an abundance of properties for formatting the control. I recommend that you format the DetailsView control by taking advantage of Cascading Style Sheets. All the following properties expose a Style object that includes a CssClass property:

  • CssClass—. Enables you to associate a style sheet class with the DetailsView control.

  • AlternatingRowStyle—. Represents every other row rendered by the DetailsView control.

  • CommandRowStyle—. Represents the row that contains the edit buttons.

  • EditRowStyle—. Represents rows when the DetailsView control is in Edit mode.

  • EmptyDataRowStyle—. Represents the row displayed when the data source does not return any data items.

  • FieldHeaderStyle—. Represents the cell displayed for the field labels.

  • FooterStyle—. Represents the footer row.

  • HeaderStyle—. Represents the header row.

  • InsertRowStyle—. Represents rows when the DetailsView control is in Insert mode.

  • PagerStyle—. Represents the row or rows that display the paging user interface.

  • RowStyle—. Represents the rows displayed by the DetailsView control.

    Furthermore, you can take advantage of the following properties when formatting a DetailsView control:

  • GridLines—. Enables you to specify the appearance of the rules that appear around the cells of the table rendered by a DetailsView control. Possible values are None, Horizontal, Vertical, and Both.

  • HeaderText—. Enables you to specify text that appears in the header of the DetailsView control.

  • FooterText—. Enables you to specify text that appears in the footer of the DetailsView control.

The page in Listing 12.18 uses several of these properties to format a DetailsView control (see Figure 12.12).

Formatting a DetailsView control with CSS.

Figure 12.12. Formatting a DetailsView control with CSS.

Example 12.18. FormatDetailsView.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
        .movies td,.movies th
        {
            padding:10px;
        }
        .movies
        {
            border:double 4px black;
        }
        .header
        {
            letter-spacing:8px;
            font:bold 16px Arial,Sans-Serif;
            background-color:silver;
        }
        .fieldHeader
        {
            font-weight:bold;
        }
        .alternating
        {
            background-color:#eeeeee;
        }
        .command
        {
            background-color:silver;
        }
        .command a
        {
            color:black;
            background-color:#eeeeee;
            font:14px Arials,Sans-Serif;
            text-decoration:none;
            padding:3px;
            border:solid 1px black;
        }
        .command a:hover
        {
            background-color:yellow;
        }
        .pager td
        {
            padding:2px;
        }
    </style>
    <title>Format DetailsView</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <asp:DetailsView
        id="dtlMovies"
        DataSourceID="srcMovies"
        AutoGenerateInsertButton="true"
        AllowPaging="true"
        GridLines="None"
        HeaderText="Movies"
        CssClass="movies"
        HeaderStyle-CssClass="header"
        FieldHeaderStyle-CssClass="fieldHeader"
        AlternatingRowStyle-CssClass="alternating"
        CommandRowStyle-CssClass="command"
        PagerStyle-CssClass="pager"
        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,@InTheaters)"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Using the FormView Control

You can use the FormView control to do anything that you can do with the DetailsView control. Just as you can with the DetailsView control, you can use the FormView control to display, page, edit, insert, and delete database records. However, unlike the DetailsView control, the FormView control is entirely template driven.

I end up using the FormView control much more than the DetailsView control. The FormView control provides you with more control over the layout of a form. Furthermore, adding validation controls to a FormView is easier than adding validation controls to a DetailsView control.

Web Standards Note

Unfortunately, from a web standards perspective, the FormView control does, in fact, render an HTML table. It creates an HTML table that contains a single cell.

Displaying Data with the FormView Control

You can display a database record with the FormView control by using an ItemTemplate. For example, the page in Listing 12.19 displays a record from the Movies database table (see Figure 12.13).

Displaying a database record with the FormView control.

Figure 12.13. Displaying a database record with the FormView control.

Example 12.19. ShowFormView.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    </style>
    <title>Show FormView</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>Box Office Totals:</b>
        <%#Eval("BoxOfficeTotals", "{0:c}") %>
        </ItemTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,BoxOfficeTotals FROM Movies
            WHERE Id=1"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that the FormView control’s DataSourceID property points to the SqlDataSource control. The SqlDataSource control retrieves the first record from the Movies database table.

Notice that the ItemTemplate contains databinding expressions that display the values of the Title, Director, and BoxOfficeTotals columns. The Eval() method retrieves the values of these columns. The databinding expression for the BoxOfficeTotals column formats the value of the column as a currency amount.

Paging Through Data with the FormView Control

You can enable users to navigate through a set of data items by enabling paging. You can allow the FormView control to automatically render the paging interface or you can use a PagerTemplate to customize the paging interface.

The page in Listing 12.20 automatically renders an additional row that contains buttons for navigating between data items.

Example 12.20. ShowFormViewPaging.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    a
    {
        color:blue;
    }
    </style>
    <title>Show FormView Paging</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>Box Office Totals:</b>
        <%#Eval("BoxOfficeTotals", "{0:c}") %>
        </ItemTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,BoxOfficeTotals FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that the FormView in Listing 12.20 includes an AllowPaging property that is assigned the value True. Adding this property generates the paging interface automatically.

Note

Unlike the DetailsView and GridView controls, the FormView control does not support AJAX.

Warning

This section describes user interface paging. User interface paging is not an efficient method to use when paging through large record sets because all the data must be loaded into memory. In Chapter 15, “Using the ObjectDataSource Control,” you learn how to implement data source paging.

You can customize the appearance of the automatically rendered paging interface with the PagerSettings property, which exposes the PagerSettings class. The PagerSettings class supports the following properties:

  • FirstPageImageUrl—. Enables you to display an image for the first page link.

  • FirstPageText—. Enables you to specify the text for the first page link.

  • LastPageImageUrl—. Enables you to display an image for the last page link.

  • LastPageText—. Enables you to specify the text for the last page link.

  • Mode—. Enables you to select a display mode for the pager user interface. Possible values are NextPrevious, NextPreviousFirstLast, Numeric, and NumericFirstLast.

  • NextPageImageUrl—. Enables you to specify the text for the next page link.

  • NextPageText—. Enables you to specify the text for the next page link.

  • PageButtonCount—. Enables you to specify the number of page number links to display.

  • Position—. Enables you to specify the position of the paging user interface. Possible values are Bottom, Top, TopAndBottom.

  • PreviousPageImageUrl—. Enables you to display an image for the previous page link.

  • PreviousPageText—. Enables you to specify the text for the previous page link.

  • Visible—. Enables you to hide the paging user interface.

If you need to customize the appearance of the paging interface completely, then you can create a PagerTemplate. The page in Listing 12.21 uses the PagerTemplate to create a custom paging interface. The PagerTemplate displays the current page number. It also contains buttons for navigating to the previous and next page (see Figure 12.14).

Using a PagerTemplate with the FormView control.

Figure 12.14. Using a PagerTemplate with the FormView control.

Example 12.21. ShowFormViewPagerTemplate.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    .frmMovies
    {
        width:100%;
    }
    </style>
    <title>Show FormView Pager Template</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        CssClass="frmMovies"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>Box Office Totals:</b>
        <%#Eval("BoxOfficeTotals", "{0:c}") %>
        </ItemTemplate>
        <PagerTemplate>
        <hr />
        <div style="float:left">
        Page: <%# frmMovies.PageIndex + 1 %>
        </div>

        <div style="float:right;white-space:nowrap">
        <asp:LinkButton
            id="lnkPrevious"
            Text="Previous Page"
            CommandName="Page"
            CommandArgument="Prev"
            Runat="server" />
        |
        <asp:LinkButton
            id="lnkNext"
            Text="Next Page"
            CommandName="Page"
            CommandArgument="Next"
            Runat="server" />
        </div>
        </PagerTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,BoxOfficeTotals FROM Movies"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that each button contained in the PagerTemplate has both a CommandName and CommandArgument property. The CommandName is set to the value Page. The CommandArgument specifies a particular type of paging operation.

You can use the following values for the CommandArgument property:

  • First—. Navigates to the first page

  • Last—. Navigates to the last page

  • Prev—. Navigates to the previous page

  • Next—. Navigates to the next page

  • number—. Navigates to a particular page number

Editing Data with the FormView Control

You can edit a database record with the FormView control. For example, you can use the page in Listing 12.22 to edit any of the records in the Movies database table (see Figure 12.15).

Editing a record with the FormView control.

Figure 12.15. Editing a record with the FormView control.

Example 12.22. ShowFormViewEditing.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    a
    {
        color:blue;
    }
    </style>
    <title>Show FormView Editing</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        DataKeyNames="Id"
        AllowPaging="true"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>Box Office Totals:</b>
        <%#Eval("BoxOfficeTotals", "{0:c}") %>
        <hr />
        <asp:LinkButton
            id="lnkEdit"
            Text="Edit Movie"
            CommandName="Edit"
            Runat="server" />
        </ItemTemplate>
        <EditItemTemplate>
        <asp:Label
            id="lblTitle"
            Text="Movie Title:"
            AssociatedControlID="txtTitle"
            Runat="server" />
        <br />
        <asp:TextBox
            id="txtTitle"
            Text='<%# Bind("Title") %>'
            Runat="server" />
        <br /><br />
        <asp:Label
            id="lblDirector"
            Text="Movie Director:"
            AssociatedControlID="txtDirector"
            Runat="server" />
        <br />
        <asp:TextBox
            id="txtDirector"
            Text='<%# Bind("Director") %>'
            Runat="server" />
        <br /><br />
        <asp:Label
            id="lblBoxOfficeTotals"
            Text="Box Office Totals:"
            AssociatedControlID="txtBoxOfficeTotals"
            Runat="server" />
        <br />
        <asp:TextBox
            id="txtBoxOfficeTotals"
            Text='<%# Bind("BoxOfficeTotals") %>'
            Runat="server" />
        <br /><br />
        <asp:LinkButton
            id="lnkUpdate"
            Text="Update Movie"
            CommandName="Update"
            Runat="server" />
        |
        <asp:LinkButton
            id="lnkCancel"
            Text="Cancel Update"
            CommandName="Cancel"
            Runat="server" />
        </EditItemTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,BoxOfficeTotals
            FROM Movies"
        UpdateCommand="UPDATE Movies SET Title=@Title,
            Director=@Director,BoxOfficeTotals=@BoxOfficeTotals
            WHERE Id=@Id"
        Runat="server" />

    </div>
    </form>
</body>
</html>

You should notice several things about the FormView control in Listing 12.22. First, notice that the FormView control includes a DataKeyNames property that contains the name of the primary key from the data source. You need to specify a primary key when editing records.

Next, notice that the FormView control’s ItemTemplate includes a LinkButton that looks like this:

<asp:LinkButton
  id="lnkEdit"
  Text="Edit Movie"
  CommandName="Edit"
  Runat="server" />

This LinkButton includes a CommandName property with the value Edit. Clicking the link switches the FormView control into Edit mode. You could use any other control here that supports the CommandName property such as a Button or ImageButton control.

Next, notice that the FormView control includes an EditItemTemplate. This template contains the form for editing the record. Each form field uses a two-way databinding expression. For example, the form field for editing the movie title looks like this:

<asp:TextBox
  id="txtTitle"
  Text='<%# Bind("Title") %>'
  Runat="server" />

The Bind("Title") method binds the Title column to the Text property of the TextBox control.

Finally, notice that the EditItemTemplate includes both a LinkButton for updating the database record and a LinkButton for canceling the update. The LinkButton for updating the record looks like this:

<asp:LinkButton
   id="lnkUpdate"
   Text="Update Movie"
   CommandName="Update"
   Runat="server" />

This LinkButton includes a CommandName property, which has the value Update. When you click this LinkButton, the SQL statement represented by the SqlDataSource control’s UpdateCommand is executed.

Note

If you want the FormView control to be in Edit mode by default, then you can assign the value Edit to the FormView control’s DefaultMode property.

Inserting Data with the FormView Control

You can use the FormView control to insert new records into a database table. For example, the page in Listing 12.23 enables you to insert a new movie record into the Movies database table.

Example 12.23. ShowFormViewInserting.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    a
    {
        color:blue;
    }
    </style>
    <title>Show FormView Inserting</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        AllowPaging="true"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>In Theaters:</b>
        <%#Eval("InTheaters") %>
        <hr />
        <asp:LinkButton
            id="lnkNew"
            Text="New Movie"
            CommandName="New"
            Runat="server" />
        </ItemTemplate>
        <InsertItemTemplate>
        <asp:Label
            id="lblTitle"
            Text="Movie Title:"
            AssociatedControlID="txtTitle"
            Runat="server" />
        <br />
        <asp:TextBox
            id="txtTitle"
            Text='<%# Bind("Title") %>'
            Runat="server" />
        <br /><br />
        <asp:Label
            id="lblDirector"
            Text="Movie Director:"
            AssociatedControlID="txtDirector"
            Runat="server" />
        <br />
        <asp:TextBox
            id="txtDirector"
            Text='<%# Bind("Director") %>'
            Runat="server" />
        <br /><br />
        <asp:CheckBox
            id="chkInTheaters"
            Text="In Theaters"
            Checked='<%# Bind("InTheaters") %>'
            Runat="server" />
        <br /><br />
        <asp:LinkButton
            id="lnkInsert"
            Text="Insert Movie"
            CommandName="Insert"
            Runat="server" />
        |
        <asp:LinkButton
            id="lnkCancel"
            Text="Cancel Insert"
            CommandName="Cancel"
            Runat="server" />
        </InsertItemTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters
            FROM Movies"
        InsertCommand="INSERT Movies (Title,Director,InTheaters)
            VALUES (@Title,@Director,@InTheaters)"
        Runat="server" />

    </div>
    </form>
</body>
</html>

You should notice several things about the page in Listing 12.23. First, notice that the ItemTemplate includes a LinkButton control that looks like this:

<asp:LinkButton
  id="lnkNew"
  Text="New Movie"
  CommandName="New"
  Runat="server" />

When you click this LinkButton control, the FormView switches into Insert mode and displays the contents of the InsertTemplate. Notice that the CommandName property has the value New.

The FormView control includes an InsertItemTemplate that contains the form for inserting a new movie record. Each form field uses a two-way databinding expression. For example, the InTheaters CheckBox looks like this:

<asp:CheckBox
  id="chkInTheaters"
  Text="In Theaters"
  Checked='<%# Bind("InTheaters") %>'
  Runat="server" />

The Bind("InTheaters") method binds the value of the CheckBox control’s Checked property to the InTheaters database column.

The InsertItemTemplate contains a LinkButton for inserting the record and a LinkButton for canceling the insert operation. The LinkButton for inserting a record looks like this:

<asp:LinkButton
  id="lnkInsert"
  Text="Insert Movie"
  CommandName="Insert"
  Runat="server" />

Notice that this LinkButton control includes a CommandName property that has the value Insert. When you click the LinkButton, the SQL command represented by the SqlDataSource control’s InsertCommand is executed.

Note

You can place the FormView control into Insert mode by default by assigning the value Insert to the control’s DefaultMode property.

Deleting Data with the FormView Control

You can use the FormView control to delete database records. For example, the page in Listing 12.24 enables you to delete records from the Movies database table (see Figure 12.16).

Deleting a record with the FormView control.

Figure 12.16. Deleting a record with the FormView control.

Example 12.24. ShowFormViewDeleting.aspx

<%@ Page Language="VB" %>
<!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">
    <style type="text/css">
    html
    {
        background-color:silver;
    }
    #content
    {
        margins:auto;
        width:600px;
        padding:10px;
        background-color:white;
        font:14px Georgia,Serif;
    }
    a
    {
        color:blue;
    }
    </style>
    <title>Show FormView Deleting</title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="content">

    <asp:FormView
        id="frmMovies"
        DataSourceID="srcMovies"
        DataKeyNames="Id"
        AllowPaging="true"
        Runat="server">
        <ItemTemplate>
        <h1><%# Eval("Title") %></h1>
        <b>Directed By:</b>
        <%# Eval("Director") %>
        <br />
        <b>In Theaters:</b>
        <%#Eval("InTheaters") %>
        <hr />
        <asp:LinkButton
            id="lnkDelete"
            Text="Delete Movie"
            CommandName="Delete"
            OnClientClick="return confirm('Are you sure?'),"
            Runat="server" />
        </ItemTemplate>
    </asp:FormView>

    <asp:SqlDataSource
        id="srcMovies"
        ConnectionString="<%$ ConnectionStrings:Movies %>"
        SelectCommand="SELECT Id,Title,Director,InTheaters
            FROM Movies"
        DeleteCommand="DELETE Movies WHERE Id=@Id"
        Runat="server" />

    </div>
    </form>
</body>
</html>

Notice that the FormView control includes a DataKeyNames property, which contains the name of the primary key column from the data source. When deleting records with the FormView control, you need to indicate the primary key column.

Furthermore, notice that the ItemTemplate includes a LinkButton for deleting a record. The LinkButton looks like this:

<asp:LinkButton
  id="lnkDelete"
  Text="Delete Movie"
  CommandName="Delete"
  OnClientClick="return confirm('Are you sure?'),"
  Runat="server" />

This LinkButton includes a CommandName property that has the value Delete. When you click the LinkButton, the SQL command represented by the SqlDataSource control’s DeleteCommand property is executed.

Notice, also, that the LinkButton includes an OnClientClick property that calls the JavaScript confirm() method to display a confirmation dialog box. This extra script prevents users from accidentally deleting database records.

Summary

In this chapter, you learned how to work with individual database records by using the DetailsView and FormView controls. You learned how to use both controls to display, page, edit, insert, and delete database records. You also learned how to format the appearance of both controls.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset