ASP.NET Data Control Series - Part 2

By Douglas Minnaar

Part 2 of the ASP.NET Data Control Series continues. In this article, the FormView DataControl is given a closer inspection.

ASP.NET 2.0 Data Controls

Author: Douglas Minnaar

The intent of this series is to provide more information concerning the functionality and limitations of the available ASP.NET 2.0 data controls. This will mostly be demonstrated through the use of code samples. Once this series is complete, I will demonstrate how one can AJAX enable some of these samples to improve the overall user experience. Therefore, this series will address the basics first before moving onto more advanced tools. Many will feel that there is enough information available concerning these matters. However, for completeness sake, I feel it is important to provide a good foundation from which to launch future articles from. The articles in this series will address typical scenarios that one might encounter in terms of developing with ASP.NET data controls.

There will be three parts in this series:

  • Part 1 – ASP.NET GridView
  • Part 2 – ASP.NET FormView and DetailsView
  • Part 3 – ASP.NET Repeater and DataList

The SqlDataSource control is used throughout the series for simplicities sake.

Part 2 - ASP.NET FormView Data Control

This is the second article in a three part series of articles pertaining to the understanding and application of ASP.NET 2.0 data controls. This article will address common functionality that may be required from ASP.NET FormView data controls.

Level: Novice - Intermediate

Prerequisites:

  • In order for the sample code to run, one will require the Pubs database running on either SqlExpress or Sql2005.
  • An understanding of C# and ASP.NET development code

Please download the code here

Introduction

Based on various Microsoft documentation, the ASP.NET FormView can be summarised as follows.

Displays the values of a single record from a data source using user-defined templates. The FormView control allows you to edit, delete, and insert records. It is similar to the DetailsView control, except it displays user-defined templates instead of row fields.

The FormView control supports the following features:

  • Binding to data source controls, such as SqlDataSource and ObjectDataSource.
  • Built-in inserting capabilities.
  • Built-in updating and deleting capabilities.
  • Built-in paging capabilities.
  • Programmatic access to the FormView object model to dynamically set properties, handle events, and so on.
  • Customizable appearance through user-defined templates, themes, and styles.

Example Details

For this example, a SqlDataSource is used to retrieve a list of authors from the database. A FormView will be used to display Author information. For each Author, a list of book titles is loaded into a GridView data control. The Titles GridView is nested within the FormView data control as a master/detail setup. The FormView behaving as the master and the Tiels GridView as the detail. Also, one is able to open a modal dialog displaying publisher information that an Author is related to. It is alos possible to add a new Title to an author from the Author FormView data control. Therefore, not only does the Author FormView have a GridView nested within it, but also another FormView data control. The whole point of this exercise is to highlight how easy it is to provide rich edit functionality using the FormView data control.

We will be using the SqlDataSource as a data provider in this example. The example will demonstrate the following features:

  • Bind FormView to a SqlDataSource (It should be noted that I only use the SqlDataSource for demonstration purposes. I favour the ObjectDataSource over the SqlDataSource in terms of the development I have been involved in)
  • Search data using a query statement, ASP.NET control parameters, and ASP.NET controls (TextBox and DropDownList) as the input
  • Edit and Update behaviour with the ASP.NET RequiredFieldValidator and CompareValidator controls.
  • Delete with confirmation dialog
  • Master/Details using a modal dialog
  • Master/Detail between FormView (master) and GridView (detail)
  • Using the DataBound event
  • Implement custom Paging

Note: Please refer to the solution code concerning the following scenarios.

 

Bind FormView to a SqlDataSource

For this example, a SqlDataSource is used as the FormView data source. The FormView DataSourceID is set to the id of the SqlDataSource. Because paging functionality will be demonstrated, AllowPaging is set to true. The DataKeyNames property is used as a primary key/s (value that uniquely identifies a record) and is set to the author id (au_id).

<asp:FormView ID="AuthorFormView"

  runat="server" AllowPaging="True"

  DataKeyNames="au_id" DataSourceID="AuthorSqlDataSource"

  Width="800px" OnDataBound="AuthorFormView_DataBound"

  OnModeChanged="AuthorFormView_ModeChanged">

The OnModeChanged event is used to determine what mode the Author FormView data control is in. In this case we use it to determine whether the Author FormView is in edit or insert mode. If it is, the Search Panel is disabled.

protected void AuthorFormView_ModeChanged(object sender,

  EventArgs e)

{

  if (AuthorFormView.CurrentMode == FormViewMode.Edit

    || AuthorFormView.CurrentMode == FormViewMode.Insert)

  {

    SearchPanel.Enabled = false;

  }

  else

  {

    SearchPanel.Enabled = true;

  }

}

The result from binding to the SqlDataSource is demonstrated as follows.



Search data

This example demonstrates how to search data within the context of a FormView control

The following code highlights the setup for the ASP.NET controls that are used as part of the search.

This is the ASP.NET code required for the setup of the Search Panel

<asp:Panel ID="SearchPanel" CssClass="Panel"

   runat="server" Width="800px">

   <fieldset class="Panel">

     <legend><strong>Search</strong></legend>

     <table width="800px" cellpadding="6px">

       <tr>

         <td>

             Author:&nbsp;<asp:TextBox ID="AuthorSearchTextBox"

             runat="server" Width="200px" /></td>

         <td>

             Publisher:&nbsp;<asp:DropDownList

             ID="PublisherSearchDropDownList"

             runat="server" Width="204px"

            OnDataBound="PublisherSearchDropDownList_OnDataBound"

             DataSourceID="PublisherSqlDataSource"

             DataTextField="pub_name"

             DataValueField="pub_id" /></td>

       </tr>

       <tr>

         <td colspan="2">

           <asp:Button ID="AuthorSearchButton"

             Text="Search" runat="server"

             BackColor="LightSteelBlue" /></td>

       </tr>

     </table>

   </fieldset>

</asp:Panel>

The result is as follows.





The Author FormView SqlDataSource is setup as follows to retrieve data based on search criteria. ASP Control Parameters are used as Select parameters

<SelectParameters>

  <asp:ControlParameter ControlID="AuthorSearchTextBox"

    Name="author" PropertyName="Text" DefaultValue=" " />

  <asp:ControlParameter ControlID="PublisherSearchDropDownList"

     DefaultValue=" " Name="publisher"

     PropertyName="SelectedItem.Text" />

</SelectParameters>

The SQL Select command is setup as follows.

SelectCommand="SELECT DISTINCT A.* FROM [Authors] A LEFT JOIN [TitleAuthor] TA ON A.au_id = TA.au_id LEFT JOIN [Titles] T ON TA.title_id = T.title_id LEFT JOIN Publishers P ON T.pub_id = P.pub_id WHERE (A.au_lname like '%' + @author + '%' OR A.au_fname like '%' + @author + '%' OR @author = '') AND (P.pub_name LIKE '%' + @publisher + '%' OR @publisher = '') ORDER BY A.au_lname ASC"

One can search by Author AND/OR Publisher. The results are as follows.




 

Edit and Update behaviour with the ASP.NET RequiredFieldValidator and CompareValidator controls

For this scenario please refer to the solution code.

The point of this scenario is to illustrate how one might nest data controls in order to achieve rich edit functionality. In this scenario, a FormView (New Title) and a GridView (Title Detail) is nested within a FormView (Author Detail).

The following screen shot illustrates that when a record is in edit mode; all author detail is required and cannot be left empty. If an attempt is made to update the row, a client-side validation event is raised to indicate that the author fields are required. It should also be noted that the Title GridView now provides an edit option. Also, one is able to add a new Title from this point.

The code to setup the Command Buttons to put the FormView in Edit or New mode is demosntrated as follows. Take note of the CommandName property.

<tr>

  <td colspan="5">

    <asp:LinkButton ID="EditButton"

      runat="server" CausesValidation="False"

      CommandName="Edit" Text="Edit" />

    <asp:LinkButton ID="DeleteButton"

      runat="server" CausesValidation="False"

      CommandName="Delete"

      OnClientClick="return ConfirmDelete();"

      Text="Delete" />

    <asp:LinkButton ID="NewButton"

      runat="server" CausesValidation="False"

      CommandName="New" Text="New" />

  </td>

</tr>

 

Edit an Author


 

Edit Title for Author

<tr>

  <td colspan="5">

    <asp:LinkButton ID="InsertTitleButton"

      runat="server" CausesValidation="True"

      CommandName="Insert" Text="Insert"

      ValidationGroup="NewTitleValidationGroup">

    </asp:LinkButton>

    <asp:LinkButton ID="InsertCancelTitleButton"

      runat="server" CausesValidation="False"

      CommandName="Cancel" Text="Cancel">

    </asp:LinkButton>

  </td>

</tr>


 

Add new Title


 

Delete with confirmation dialog

Unfortunately, there is no setting that one can enable to allow one to have a confirmation dialog popup should a delete action be initiated. The following snippet demonstrates a way that one might use to create this kind of behaviour.

Add some javascript to prompt a user before removing an item.

/**

 * Raise a confirmation dialog to confirm the requested deletion

 * of a record

 **/

function ConfirmDelete()

{

  return confirm("Are you sure you wish to remove the selected item?");     

}


An ‘OnClientClick’ event handler is configured for the Delete ImageButton. The event handler will execute the ‘ConfirmDelete()’ javascript function.

<asp:LinkButton ID="DeleteButton"

  runat="server" CausesValidation="False"

  CommandName="Delete" OnClientClick="return ConfirmDelete();"

  Text="Delete" />


The resultant behaviour is as follows.


 

Master/Details using a modal dialog

The following code snippet demonstrates how one might open a dialog window from a FormView control. When the ‘Show Publisher Detail’ link button is clicked, a modal dialog will be opened. Upon opening, the dialog window will load a FormView control with a summary of Publisher detail based on AuthorID. The AuthorID is passed as a parameter as part of the javascript code required to open a modal dialog as can be seen in the snippet below.

/**

 * Show a modal dialog that will load a page containing a GridView

 * that will be populated with OrderDetail records based on the

 * provided 'PRoductID'

 */

function ShowPublisherDetail(AuthorID)

{

  window.showModalDialog("PublisherInfo.aspx?AuthorID=" + AuthorID, "",

  "dialogWidth:430px;dialogHeight:200px;resizable:no;scrollbars:no");

}

A static method (GetClientClick()) in the code behind is used as part of this functionality.

protected static string GetClientClick(object value)

{

  return String.Format(

    "ShowPublisherDetail('{0}'); return false;",

    value.ToString());

}

The 'Show Publisher Detail' Link Button is configured as follows.

<tr>

  <td colspan="5">

    <asp:LinkButton ID="ShowPublisherDetailLinkButton"

      runat="server" Text="Show Publisher Detail"

      OnClientClick='<%# GetClientClick(Eval("au_id")) %>' />

  </td>

</tr>

The result is as follows.


 

Master/Detail between FormView (master) and GridView (detail)

For each Author record that is retrieved, a GridView will be loaded with titles that have been authored according to the author id. The Author FormView behaves as the Master providing the AuthorId.

Please refer to the solution code for this example.

 

Implement custom Paging

It is possible to provide rich paging functionality by editing the PagerTemplate of the FormView. The following code snippets illustrate how this is achieved. Please refer to the following code in the actual code solution.

The following code illustrates the ASP.NET settings required to implement a custom paging template. Please take note of the ‘CommandArgument’ and ‘CommandName’ attributes.

<PagerSettings Mode="NextPreviousFirstLast"

  Position="TopAndBottom" />

<PagerTemplate>

  <asp:Panel ID="PagerTemplatePanel"

    runat="server" CssClass="ItemTemplatePanel"

    BackColor="lightsteelblue" Width="800px">

    <table width="800px">

      <tr valign="middle">

        <td style="text-align: right; width: 340px">

          <asp:ImageButton ID="FirstPageImageButton"

            runat="server" AlternateText="First Page"

            CommandName="Page" CommandArgument="First"

            ImageUrl="~/Images/Bullets/left.gif" />

          <asp:ImageButton ID="PreviousPageImageButton"

            runat="server" AlternateText="Previous Page"

            CommandName="Page" CommandArgument="Prev"

            ImageUrl="~/Images/Bullets/left2.gif" />

        </td>

        <td style="text-align: center;

          width: 120px">

          Page&nbsp;<asp:DropDownList ID ="PageNumberDropDownList"

            AutoPostBack="true"

            OnSelectedIndexChanged="PageNumberDropDownList_OnSelectedIndexChanged"

            runat="server" />&nbsp;of&nbsp;<asp:Label

              ID="PageCountLabel" runat="server" />

        </td>

        <td style="text-align: left; width: 340px">

          <asp:ImageButton ID="NextPageImageButton"

            runat="server" AlternateText="Next Page"

            CommandName="Page" CommandArgument="Next"

            ImageUrl="~/Images/Bullets/right2.gif" />

          <asp:ImageButton ID="LastPageImageButton"

            runat="server" AlternateText="Last Page"

            CommandName="Page" CommandArgument="Last"

            ImageUrl="~/Images/Bullets/right.gif" />

        </td>

      </tr>

    </table>

  </asp:Panel>

</PagerTemplate>

 

The following code illustrates the initlaisation code required to enable the required custom paging functionality.

 

/// <summary>

/// Initialise Pager Row Settings

/// </summary>

private void InitialiseFormViewPagerRow(FormViewRow formViewRow)

{

  if (formViewRow != null)

  {

    // Check the page index so that we can :

    //  1. Disable the 'First' and 'Previous' paging image buttons if paging index is at 0

    //  2. Disable the 'Last' and 'Next' paging image buttons if paging index is at the end

    //  3. Enable all image buttons if the conditions of 1 and 2 are not satisfied

 

    if (AuthorFormView.PageIndex == 0)

    {

      // Disable 'First' and 'Previous' Paging image buttons

 

      ImageButton firstPageImageButton = formViewRow.FindControl(

        "FirstPageImageButton") as ImageButton;

 

      ImageButton previousPageImageButton = formViewRow.FindControl(

        "PreviousPageImageButton") as ImageButton;

 

      if (firstPageImageButton != null && previousPageImageButton != null)

      {

        firstPageImageButton.Enabled = false;

 

        previousPageImageButton.Enabled = false;

      }

    }

    else if ((AuthorFormView.PageIndex + 1) == AuthorFormView.PageCount)

    {

      // Disable 'Last' and 'Next' Paging image buttons

 

      ImageButton lastPageImageButton = formViewRow.FindControl(

        "LastPageImageButton") as ImageButton;

 

      ImageButton nextPageImageButton = formViewRow.FindControl(

        "NextPageImageButton") as ImageButton;

 

      if (lastPageImageButton != null && nextPageImageButton != null)

      {

        lastPageImageButton.Enabled = false;

 

        nextPageImageButton.Enabled = false;

      }

    }

    else

    {

      // Enable the Paging image buttons

 

      ImageButton firstPageImageButton = formViewRow.FindControl(

        "FirstPageImageButton") as ImageButton;

 

      ImageButton previousPageImageButton = formViewRow.FindControl(

        "PreviousPageImageButton") as ImageButton;

 

      ImageButton lastPageImageButton = formViewRow.FindControl(

        "LastPageImageButton") as ImageButton;

 

      ImageButton nextPageImageButton = formViewRow.FindControl(

        "NextPageImageButton") as ImageButton;

 

      if (firstPageImageButton != null && lastPageImageButton != null &&

        previousPageImageButton != null && nextPageImageButton != null)

      {

        firstPageImageButton.Enabled = true;

 

        lastPageImageButton.Enabled = true;

 

        nextPageImageButton.Enabled = true;

 

        previousPageImageButton.Enabled = true;

      }

    }

 

    // Get the DropDownList found as part of the Pager Row.

    // One can then initialise the DropDownList to contain

    // the appropriate page settings. Eg. Page Number and

    // number of Pages

    DropDownList pageNumberDropDownList = formViewRow.FindControl(

      "PageNumberDropDownList") as DropDownList;

 

    Label pageCountLabel = formViewRow.FindControl(

      "PageCountLabel") as Label;

 

    if (pageNumberDropDownList != null && pageCountLabel != null)

    {

      for (int i = 0; i < AuthorFormView.PageCount; i++)

      {

        int page = i + 1;

 

        pageNumberDropDownList.Items.Add(new ListItem(

          page.ToString(), i.ToString()));

      }

 

      pageNumberDropDownList.SelectedIndex = AuthorFormView.PageIndex;

 

      pageCountLabel.Text = AuthorFormView.PageCount.ToString();

    }

  }

}

 

/// <summary>

/// Handle the SelectedIndexChanged event for the Page Number

/// DropDownList. This allows one to select a page index via a

/// DropDownList.

/// </summary>

protected void PageNumberDropDownList_OnSelectedIndexChanged(

  object sender, EventArgs e)

{

  DropDownList pageNumberDropDownList = sender as DropDownList;

 

  if (pageNumberDropDownList != null)

  {

    if (AuthorFormView.DataItemCount > 0)

    {

      if (pageNumberDropDownList.SelectedIndex < AuthorFormView.PageCount ||

        pageNumberDropDownList.SelectedIndex >= 0)

      {

        AuthorFormView.PageIndex = pageNumberDropDownList.SelectedIndex;

      }

    }

  }

}

The result of the aforementioned code is illustrated in the image below.


 

That’s it for Part 2 of ASP.NET data controls. Part 3 will address the ASP.NET DetailView and Repeater data controls.

Popularity  (15921 Views)
Biography - Douglas Minnaar
After pursuing an Electronic Engineering diploma for several years, Douglas Minnaar worked as an Electronic Technician where he was involved with a number of engineering projects that mostly involved working with digital electronic systems. It was during this time that Douglas discovered his passion for software development. Douglas then went back to pursue a degree in Computer Science majoring in distributed computing systems. He has been practicing as a software developer predominantly in the Microsoft .NET space ever since.
Create New Account
Article Discussion: ASP.NET Data Control Series - Part 2
Douglas Minnaar posted at Saturday, July 14, 2007 3:20 PM
reply
SqlDataSource concern
Eric M replied to Douglas Minnaar at Monday, July 16, 2007 7:48 AM

Sir,

I’ve come across your article ASP.NET Data Control Series – Part 2 in which you use a custom paging in the form view. I have a similar task where I have form view and I need to be able to page through several records.

 

I, however don’t use SqlDataSource, instead the architecture is layout over 3 layers. In some instances we use ObjectDataSource with SeletecMethod and TypeName properties. In other instances we just reference the BLL directly in the code behind.

 

The built-in paging that FormView + SqlDataSource combination offers is very attractive but it is outside of CM and not only that, I don’t want to expose any part of database info in the SqlDataSource mainly the Sql commands and connection strings.

 

So is there a way to use ODS and still have the rich paging feature? Or, can the SDS point to my BLL using some kind of SelectMethod like in ODS? Or, is there way to encrypt the Sql command and/or the connection string?

 

Thanks,

 

EJM

 

reply
Thank You!
Dennis Davis replied to Douglas Minnaar at Monday, July 16, 2007 7:48 AM

Mr. Minnaar,

Your 3 articles on ASP.NET Data Controls are all well-written and easy to follow -- excellent job!  I am an experienced developer but new to web programming, so this was a big help. 

So often I come across articles and partial code snippets where the authors never show screen images of what the Page actually looks like. You provided this and more -- I downloaded the code, compiled it, and it worked "as is" (after changing web.config to point to my development SQL Server).

Thank you for such a thorough, well done article.

-Dennis

reply
why code-behind for binding?
Bryan Nilsen replied to Douglas Minnaar at Monday, July 16, 2007 7:48 AM

Why is it that you used code-behind for binding? Why not use the inbuilt #bind feature of FormView instead?

reply