When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, July 11, 2007

Displaying Extended Details in a GridView Using an Ajax Pop-Up (Part 2)

By Brian Smith


Introduction


This two-part article series examines how to use Microsoft's ASP.NET AJAX to add a pop-up control to a GridView in order to display drill-down detail information in a responsive and clean manner. In Part 1 we looked at displaying the list of employees from the Northwind database in a GridView. This involved building an application architecture consisting of a Data Access Layer (DAL) created via Typed DataSets and a Business Logic Layer (BLL) created as custom classes. We then created an ASP.NET page that used a GridView and an ObjectDataSource to invoke the appropriate BLL method and display the results.

In this second and final installment we'll turn our attention to Ajax-ifying the GridView by adding the pop-up control to display the territories coverred by the moused over employee. This will involve creating a dynamic populate page method that will be called asynchronously from the browser when the user mouses over an employee. This call back to the web server will return the specified employee's list of territories, which will then be displayed in the pop-up. Read on to learn more!

- continued -

A Quick Review of the GridView Report


In Part 1 we created a GridView that displayed the set of employees in the Northwind database's Employees table. This was accomplished using an ObjectDataSource that called down into our BLL, which invoked a DAL method, which ran a stored procedure that executed a SELECT statement. The database records returned from the database were loaded into a strongly-typed DataTable (EmployeesDataTable) and returned to the BLL, which returned it to the ObjectDataSource, which then bound it to the GridView. Also, since we created our website as an AJAX Control Toolkit website, Default.aspx included a ScriptManager control by default.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!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 runat="server">
   <title>Untitled Page</title>
</head>
<body>
   <form id="form1" runat="server">
      <ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
      <div>
         <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" OldValuesParameterFormatString="original_{0}"
            SelectMethod="GetEmployees" TypeName="EmployeesBLL"></asp:ObjectDataSource>
      </div>
      <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Employeeid"
         DataSourceID="ObjectDataSource1">
         <Columns>
            <asp:BoundField DataField="EamployeeID" HeaderText="EmployeeID" SortExpression="EmployeeID"/>
            <asp:BoundField DataField="Name" HeaderText="Name" ReadOnly="True" SortExpression="Name" />
            <asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
            <asp:BoundField DataField="Address" HeaderText="Address" SortExpression="Address" />
            <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
            <asp:BoundField DataField="PostalCode" HeaderText="PostalCode" SortExpression="PostalCode" />
            <asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" />
         </Columns>
      </asp:GridView>
   </form>
</body>
</html>

Our next step is to put in the controls and functionality to facilitate the ASP.NET AJAX pop-up control. Before you move onto this task, make sure you have read Part 1 and understand the concepts. The complete code is available for download at the end of this article. If you are following along at your own pace, make sure that you have the simplified report from Part 1 working before tackling Part 2.

Adding the Pop-Up Control


As noted in Part 1, our end report will contain a column of magnifying glasses. To see the details for a particular employee, a user will simply mouse over that employee's magnifying glass icon. To accomplish this, we need three additional controls on the web page: an ASP.NET Image control (for the magnifying glass icon), an AJAX PopUpControlExtender, and an ASP.NET Panel control. The first two controls will be added to a TemplateField column in the GridView; the Panel will be added inline after the GridView control and is used to display the moused over employee's details.

To start, click the Edit Columns option from the GridView's smart tag to bring up the Fields editor. Remove the EmployeeID column and then add a new TemplateField to the column list.

Remove the EmployeeID column and then add a new TemplateField to the column list.

Move the TemplateField column up the list so it's the second item, just under Name, and click OK. At this point the GridView in the Visual Studio Designer should look similar to the following:

The GridView, as seen in the Visual Studio Designer.

Note that there is no longer an EmployeeID column. The TemplateField we just added is between the Name and Title columns; since we've yet to add any content for the column, it currently appears as a collapsed column.

Let's add the content to the TemplateField we just added. In the Designer, right-click the new TemplateField and choose Edit Tempate --> Column[1]). Upon doing so the GridView's appearance in the Designer will change to display a control that contains five Template "designer" surfaces. You can drag and drop controls from the Toolbox onto any of these templates; alternatively, you can place the cursor inside these templates and enter text directly through by typing. We want to add an Image Web control to the ItemTemplate design surface.

Drag an Image control from the Standard Toolbox tab and a PopUpControlExtender from the AJAX Controls tab (or whatever name you gave it when you created it) to the TemplateField's ItemTemplate. If you do not see the PopUpControlExtended option in the Toolbox, make sure that you have installed the ASP.NET AJAX Control Toolkit and that you have added it to the Toolbox. See How Do I: Get Started with the ASP.NET AJAX Control Toolkit? for more information on these steps.

From the PopUpColtrolExtender's smart tag, choose "Add Dynamic Populate Page Method."

From the PopUpColtrolExtender's smart tag, choose Add Dynamic Populate Page Method.

The method it adds to your page's code-behind class will be called when an Ajax postback is triggered. The parameter in the method must be named contextkey. Also, the name of this method is important; feel free to change it, but it is important that you remember this change for later. Here's the code for the method that was generated in the code-behind class:

[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string GetDynamicContent(string contextKey)
{
   return default(string);
}

We'll come back and complete the code for this method later. For now, let's complete our task of adding the controls to the page.

Drag a Panel control onto the Designer beneath the GridView control and clear its Width and Height properties.

We are now ready to configure the PopUpColtrolExtender control's properties. Unfortunately, only a subset of the control's properties are available through the Properties window. Therefore, we need to enter some properties through the page's declarative markup. Click on the Source tab in the lower left corner to switch to the declarative markup. Update the PopUpColtrolExtender control's markup so that it looks like the following:

<ajaxToolkit:PopupControlExtender
   ID="PopupControlExtender1"
   runat="server"
   DynamicServiceMethod="GetDynamicContent"
   DynamicContextKey='<%# Eval("EmployeeID") %>'
   DynamicControlID="Panel1"
   TargetControlID="Image1"
   PopupControlID="Panel1"
   Position="right">
</ajaxToolkit:PopupControlExtender>

The above markup adds six attributes to the PopUpControlExtender. They are:

  • DynamicServiceMethod - this property specifies the method to execute on the server when the pop-up window is displayed. Note the value is the same as the method named defined for us above. If you changed the name of the method generated when clicking the pop-up control's "Add Dynamic Populate Page Method" option, make sure that the name change is reflected in this property as well.
  • DynamicContextKey - this is the string value passed to the server-side method. Here we use databinding syntax to pass in the current employee's EmployeeID field value.
  • DynamicControlID - this is the control on the page that receives and displays the returned value from our method above.
  • TargetControlID - this is the control that the PopUpControlExtender watches. This control must implement a postback in order to work.
  • PopUpControlID - this is the control to "pop-up". In this case it's the Panel we added earlier.
  • Position - acceptable values are Top, Left, Bottom, Right, Center. This controls the position of the "Pop-up" relative to the TargetControlID. Alternatively, you can use the OffseX and OffsetY properties to more accurately specify the distance from the target control.

Returning the List of Territories Covered by an Employee


When the pop-up control is "executed" it makes a partial page postback, which runs the method specified via the DynamicServiceMethod property (GetDynamicContent, in our example). The GetDynamicContent method returns HTML that is then displayed by the specified control (Panel1, in our example). Therefore, we need to write the code for the GetDynamicContent method such that it returns the list of territories for the specified employee.

The following code uses a StringBuilder to build up the resulting HTML. The TerritoriesBLL class is used to retrieve the list of territories covered by the specified employee. The resulting rows are enumerated and an HTML <table> is constructed and returned.

[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string GetDynamicContent(string contextKey)
{
   StringBuilder sTemp = new StringBuilder();
   TerritoriesBLL oTerritories = new TerritoriesBLL();
   Northwind.EmployeeTerritoriesDataTable ts = oTerritories.SelectTerritories(Convert.ToInt32(contextKey));

   if (ts.Rows.Count > 0)
   {
      sTemp.Append("<table>");
      sTemp.Append("<tr><td><b>Territories:</b></td></tr>");

      foreach (Northwind.EmployeeTerritoriesRow t in ts)
      {
         sTemp.Append("<tr><td>" + t.Territory + "</td></tr>");
      }

      sTemp.Append("</table>");
   }
   else
      sTemp.Append("<i>This employee covers no territories...</i>");

   return sTemp.ToString();
}

Page Method Versus Web Service
The pop-up control can be configured to either call a method in the page's code-behind class or a method of a Web Service. If you expect that the particular data displayed in the pop-up (the list of territories for a particular employee, in this application) will be needed on other pages, it might make sense to create a Web Service with the method rather than having to recreate this method in each page where a pop-up is needed. My demo uses the method at the page-level. Feel free to experiment with the Web Service approach. To do so, you will need to create a Web Service and set the pop-up control's DynamicServicePath to the path of the Web Service endpoint.

Displaying the Pop-Up When Mousing Over the Magnifying Glass Icon


If you tested your progress after entering the code for the GetDynamicContent method, you would have noticed that mousing over the magnifying glass icon does not display the pop-up. However, clicking the image does bring up the pop-up control, although it's current appearance is quite hideous - we'll fix that in a second. In order to have the pop-up display when mousing over the image we need to add an event handler for the GridView's RowCreated event that programmatically references the Image control and adds client-side onmouseover and onmouseout events that show and hide the Panel. In particular, we need to call the AJAX toolkit client-side library to show (or hide) the popup when the user mouses over (or out) the Image.

To create an event handler, select the GridView in the Designer and then go to the Properties window. Click the lightning bolt and then double-click the RowCreated event. This will create an empty event handler in the page's code-behind class. Update it so that it has the following code:

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
      // Programmatically reference the PopupControlExtender
      PopupControlExtender pce = e.Row.FindControl("PopupControlExtender1") as PopupControlExtender;

      // Set the BehaviorID
      string behaviorID = string.Concat("pce", e.Row.RowIndex);
      pce.BehaviorID = behaviorID;

      // Programmatically reference the Image control
      Image i = (Image)e.Row.Cells[1].FindControl("Image1");

      // Add the clie nt-side attributes (onmouseover & onmouseout)
      string OnMouseOverScript = string.Format("$find('{0}').showPopup();", behaviorID);
      string OnMouseOutScript = string.Format("$find('{0}').hidePopup();", behaviorID);

      i.Attributes.Add("onmouseover", OnMouseOverScript);
      i.Attributes.Add("onmouseout", OnMouseOutScript);
   }
}

Since this event handler is fired for each row added to the GridView - including headers, footers, pagers, and so forth - it is imperative that we first check to ensure that we are dealing with a data row because only data rows have the PopupControlExtender and Image Web controls in their templates. If we are working with a data row we start by programmatically referencing the PopupControlExtender using the FindControl("controlID") method. We do this because we need to programmatically set its BehaviorID property. The BehaviorID property is used when we interface with the AJAX toolkit client-side library in order to uniquely identify the popup to show or hide. Since there is a PopupControlExtender for each GridView row, and because the BehaviorID property is used to uniquely identify each PopupControlExtender instance, we need to set the BehaviorID property programmatically here in the RowCreated event handler. Note that we choose a BehaviorID value of "pce" plus the current RowIndex (0, 1, 2, ...).

Next, we programmatically reference the Image control Image1. Finally, we set this control's client-side event handlers via the Attributes collection. When the user mouses over a particular magnifying glass icon, the showPopup() function is called to show the appropriate popup. We use the $find('BehaviorID') method to specify which popup to show. This call to showPopup() invokes an asynchronous postback which calls the GetDynamicContent method. The asynchronous call receives the HTML listing the selected employee's territories from the server, and displays it in the Panel control. When the user mouses out of the icon, the popup's hidePopup() function is called, thereby hiding the pop-up.

If you revisit this page in a browser and look at its source, you'll see that the GridView's TemplateField generated the following markup:

<td>
   <img id="GridView1_ctl02_Image1" onmouseover="$find('pceRowIndex').showPopup();" onmouseout="$find('pceRowIndex').hidePopup();" src="magglass.jpg" style="border-width:0px;" />
</td>

Look! There's our onmouseover and onmouseout events! Now the pop-up automatically displays when mousing over the magnifying glass icon and disappears once you've moused out.

Finishing Touches


As things currently stand, the pop-up window is rather insightly. As the following screen shot shows, the pop-up window is transparent, causing the GridView's text to bleed through. This makes the pop-up details difficult to read.

The pop-up window is transparent.

To remedy this you could update the HTML emitted by the GetDynamicContent method so that the <table> has a background specified. A more flexible approach, however, is to use a style sheet. Simply add the following style sheet to the page, which indicates that all <table> elements within Panel1 should have a certain border, background-color, and text color.

<style type="text/css">
   #Panel1 TABLE
   {
      border: #060F40 2px solid;
      color: #060F40;
      background: #ffffcc;
   }
</style>

After adding this style, the pop-up becomes much easier to read!

Hovering over the magnifying glass icon for a particular employee record displays details about that employee.

Conclusion


In this tutorial we learned how to use ASP.NET AJAX's pop-up control to display report details when mousing over an icon in the GridView. Please send any errata, suggestions, comments, or questions about this article to brian@brianandjeannesmith.com.

Happy Programming!

  • By Brian Smith


    Attachments


  • Download the code used in this article
  • Further Readings


  • Displaying Extended Details in a GridView Using an Ajax Pop-Up (Part 1)
  • Working with Data in ASP.NET 2.0 (Scott Mitchell's tutorial series)
  • Microsoft ASP.NET AJAX
  • Pop-Up Control Sample


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article