Skip Navigation LinksHome : CBC Classes : ASP.Net : Database 2 Detailsview

CS218 ASP.Net - The DetailsView Control


  1. DetailsView vs. GridView (video 6a1)
  2. Creating a detailviews and configuring the accessdatasource (video 6b1)
  3. Adding Records (video 6c1)
  4. Access primary key solution 1 - setting insertvisible to true (video 6c2)
  5. Access primary key solution 2 - adding vbcode (video 6c3, code)
  6. Changing appearance - autoformat (video 6d1)
  7. Changing appearance - individual rows (video 6d2)
  8. Changing appearance - controlling overall width, and column width (video 6d3)
  9. Changing appearance - template fields, creating and editing in design view (video 6e1)
  10. Changing appearance - editing template fields in source view (video 6e2)
  11. Adding images and links to a template (video 6e3)
  12. Horizontal and vertical alignment (video 6f1)
  13. Advanced detailsview topics
    1. Storing and displaying images in a database (video 6g1, code)
    2. Providing user feedback for database operations (video XXX NEED VIDEO, code)
VB Code for autonumbering the primary key

The first step is to create the subroutine that will execute when a new record is being added to the database. Open the vb file that's linked to your .aspx page. At the top of the window, select the pull down list on the left and select your accessdatasource. It's named AccessDatasource1, unless you changed it. Next, go to the pull down list at the top of the window and choose the Inserting event. You should then something very similar to the following in the editor:

   Protected Sub AccessDataSource1_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles AccessDataSource1.Inserting

   End Sub

Next, copy the following code and paste it in between the Protected Sub line and the End Sub line.

        Dim cmd As New Data.OleDb.OleDbCommand("Select MAX(ID) From yourTableName", e.Command.Connection)
        Dim newID As Long

        cmd.Connection.Open()
        newID = Int32.Parse(cmd.ExecuteScalar()) + 1
        e.Command.Parameters(0).Value = newID

You should end up with something very close to the following:

   Protected Sub AccessDataSource1_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles AccessDataSource1.Inserting
        Dim cmd As New Data.OleDb.OleDbCommand("Select MAX(ID) From yourTableName", e.Command.Connection)
        Dim newID As Long

        cmd.Connection.Open()
        newID = Int32.Parse(cmd.ExecuteScalar()) + 1
        e.Command.Parameters(0).Value = newID
   End Sub

To make this work with your database table you will only have to change one or two things in the line that reads;

    Dim cmd As New Data.OleDb.OleDbCommand("Select MAX(ID) From yourTableName", e.Command.Connection)

The ID must be set to the Primary Key Field name in your table, and yourTableName must be set to the table name (not the database name). For example, if you set your primary key to studentID and your table is named studentRecords then this line must read:

    Dim cmd As New Data.OleDb.OleDbCommand("Select MAX(studentID) From studentRecords", e.Command.Connection)

And ... that's it! You can test this by running your page and adding a new record.


Here's similar code for autonumbering in a SQL database, just in case you want to see it.

' Use this for an SQL database, which autogenerates primary keys, so you won't need this code!
' The @@IDENTITY returns the maximum ID of the primary key, without knowing the name of the 
' primary key. The only things you'll have to change are (1) yourTableName to the name of your table,
' and (2) dataSourceName to the name of your datasource control. 


    Protected Sub dataSourceName_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles dsrcAuthorDetails.Inserting
        Dim cmd As New Data.OleDb.OleDbCommand("Select @@IDENTITY From yourTableName", e.Command.Connection)
        Dim newID As Long

        cmd.Connection.Open()
        newID = Int32.Parse(cmd.ExecuteScalar())
        e.Command.Parameters(0).Value = newID
    End Sub

Storing and Displaying Images

While it's possible to store actual image files in a database table, it's difficult and it takes up a lot of storage in the database. A better alternative is to store the name of the image file. However, this requires some code to get the image to display in a detailsview template.

This is the code to add to the template(s) in your detailsview. Remember that you probably want to just display the image in the ItemTemplate. It won't be displayed in the InsertItemtemplate. You may choose to display it in the EditItemTemplate, but make sure and also display some type of input control (like a textbox or dropdown) to allow the user to change the image file.

The only change you should make is to change yourImageField to match the name of the field in your database that stores the image file name.

    <asp:Label ID="imageLabel" runat="server" 
             Text='<%# checkImage(Eval("yourImageField")) %>' >
    </asp:Label> 

This code goes in the .vb file. Put it inside the main class declaration, but outside of any other subroutines or functions. If necessary change the ../images/ to match the path to your images folder. (Here's a weird thing. Using the ~/pathname and runat='server' doesn't work in this case. You have to add the correct path. But the good news is that this isn't like the masterpage where the path will change. The path from this page to the images folder will always be the same.)

You should also change the other attributes alt='your alt text' width='340' to the appropriate values for your image.

    Function checkImage(ByVal imageString As Object) As String
        If (imageString Is DBNull.Value) Then
            Return ""
        Else
            Return "<img src='../images/" + imageString.ToString + "' alt='your alt text' width='340'  />"
        End If
    End Function

Adding A RadioButtonList to a template

Here's an example of a radioButtonList in an EditItemTemplate. The only reason I added it here is so you can copy and paste the SelectedValue, which you won't get when you create the RadioButtonList and add the database connection. (Watch the video for details on how to do this.)

Make sure and change the value in the SelectedValue from yourDatabaseField to the name of the field in your database.

   <EditItemTemplate>
     <asp:RadioButtonList ID="RadioButtonList1" runat="server" 
          DataSourceID="AccessDataSource2" DataTextField="petType" 
          DataValueField="petType" SelectedValue='<%# Bind("yourDatabaseField") %>' >
     </asp:RadioButtonList>
   </EditItemTemplate>
Providing feedback on success or failure, and trapping errors

One of the problems with adding new database records is that there's no feedback for the user unless there's an error. So if the new record is added, the user will just be returned to the detailsview. You can/should add your own feedback mechanism.

I suggest creating two panels, one for success and another for failure. On the success panel, add some text that says that the database was updated, and some buttons to either add another record or go somewhere else. On the failure panel add some text and a label, plus some buttons to return to the detailsview to correct the error, or to go somewhere else.

Set the visibility property of both these panels to false at load time.

<asp:Panel ID="PanelSuccess" runat="server" Visible="False">
<p>
The record was added to the database
</p>

<asp:Button ID="cmdAdmin" runat="server" Text="Return To Admin Page" />
<asp:Button ID="cmdViewProducts" runat="server" Text="View Products Page" />

</asp:Panel>
    
    
<asp:Panel ID="PanelFail" runat="server" Visible="False">
<p>
The following error occurred while trying to add the product listing to the database:
<asp:Label ID="lblError" runat="server" Text="Label"></asp:Label>
</p>
    
<asp:Button ID="cmdAdmin2" runat="server" Text="Return To Admin Page" />
<asp:Button ID="cmdRetry" runat="server" Text="Edit Product Information" />

</asp:Panel>

The VB code goes in the detailsviewItemUpdated event handler. The syntax for catching the error has changed a bit over the years. Here's the latest:

    Protected Sub DetailsView1_ItemInserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) Handles DetailsView1.ItemInserted

        DetailsView1.Visible = False

        If e.Exception IsNot Nothing Then
            PanelFail.Visible = True
            lblError.Text = e.Exception.Message.ToString
            e.ExceptionHandled = True
        Else
            PanelSuccess.Visible = True
        End If

    End Sub

    Protected Sub cmdViewProducts_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdViewProducts.Click
        Server.Transfer("~/products/default.aspx")
    End Sub

    Protected Sub cmdAdmin_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAdmin.Click
        Server.Transfer("default.aspx")
    End Sub

    Protected Sub cmdAdmin2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAdmin2.Click
        Server.Transfer("default.aspx")
    End Sub

    Protected Sub cmdRetry_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdRetry.Click
        PanelFail.Visible = False
        DetailsView1.Visible = True
    End Sub