• North American Sales: 1-800-231-8588
  • Global Contacts
  • My Account
Infragistics Infragistics
Menu
  • North American Sales: 1-800-321-8588
  • My Account
    • Sign In/Register
  • Design & DevelopmentDesign & Develop
    • Best Value
      Infragistics Ultimate The complete toolkit for building high performing web, mobile and desktop apps.
      Indigo.Design Use a unified platform for visual design, UX prototyping, code generation and application development.
    • Web
      Ignite UI for Angular Ignite UI for JavaScript Ignite UI for React Ultimate UI for ASP.NET Indigo.Design
    • Desktop
      Ultimate UI for Windows Forms Ultimate UI for WPF
      Prototyping
      Indigo.Design
    • Mobile
      Ultimate UI for Xamarin Ultimate UI for iOS Ultimate UI for Android
    • Automated Testing Tools
      Test Automation for Micro Focus UFT: Windows Forms Test Automation for Micro Focus UFT: WPF Test Automation for IBM RFT: Windows Forms
  • UX
    • Indigo.Design Desktop Collaborative prototyping and remote usability testing for UX & usability professionals
    • Indigo.Design A Unified Platform for Visual Design, UX Prototyping, Code Generation, and App Development
  • Business Intelligence
    • Reveal Embedded Accelerate your time to market with powerful, beautiful dashboards into your apps
    • Reveal App Empower everyone in your organization to use data to make smarter business decisions
  • Team Productivity
  • Learn & Support Support
    • Help & Support Documents
    • Blogs
    • Forums
    • Product Ideas
    • Reference Applications
    • Customer Stories
    • Webinars
    • eBook & Whitepapers
    • Events
  • Free Trials
  • Pricing
    • Product Pricing / Buy Online
    • Renew Existing License
    • Contact Us
ASP.NET
  • Product Platforms
  • More
ASP.NET
ASP.NET Building an Ajax Master/Detail Page with the WebDataGrid
  • Blog
  • Files
  • Wiki
  • Mentions
  • Tags
  • More
  • Cancel
  • New
ASP.NET requires membership for participation - click to join
  • ASP.NET
  • Accessing Extra Data in Data Bound Controls
  • ASP.NET Performance - A Place To Start
  • -Building an Ajax Master/Detail Page with the WebDataGrid
    • Implementing an Ajax Live Form with NetAdvantage WebClient Controls
  • Building WebParts with NetAdvantage ASP.NET Controls
  • Data Binding the WebDataGrid to Common Data Sources
  • Getting Started with NetAdvantage ASP.NET
  • HTML5 Mode and Other Goodness in the WebRating Control
  • Implementing WebDataGrid Client Side Search
  • Introduction to the Infragistics Web Drag and Drop Framework
  • Learn to Build a WebDataGrid Custom Pager
  • Understanding Script Combining
  • Using ADO.NET to Perform CRUD Operations with the WebDataGrid
  • WebDataGrid 101: Fill the Grid with Data and Change the Look and Feel
  • +WebDataGrid : Import data from Excel & Export to Excel, PDF or XPS
  • WebDataGrid Client-Side CRUD
  • WebDataGrid DataViewState vs ViewState
  • WebDataGrid Validation

Building an Ajax Master/Detail Page with the WebDataGrid

NetAdvantage 2008 Volume 3 ushered in the release of the new WebDataGrid. In order to help you get familiar with this all-new control build on the Infragistics Akido framework, I will take you step-by-step through building an AJAX master/detail page.

Activation Behavior

At the root of enabling the interaction found in this approach is the Activation behavior. When enabled activation will fire client-side and server-side events giving you hooks into controlling what happens before and after active cells are changed on the grid.

Data Source

This sample uses the BookRepository as a data source. BookRepository is a light-weight and portable way for creating data for demonstrations. Read more about the BookRepository here.

Setup the Grid

To begin you will start by setting up the WebDataGrid and adding the necessary support controls to enable interaction with the data.

  1. Add a ScriptManager to the page
  2. Next, drag a WebDataGrid from the toolbox to the page
  3. Change the ID to "dg"
  4. Set the AutoGenerateColumns to false

Next you will explicitly define the markup for the Title column. Switch to the Source view and enter the following markup inside the WebDataGrid tag:

view plaincopy to clipboardprint
  1. <Columns>  
  2.     <ig:TemplateDataField Key="Title">  
  3.         <ItemTemplate>  
  4.             <asp:Placeholder ID="Placeholder1" runat="server">  
  5.                 <%# DataBinder.Eval(((Infragistics.Web.UI.TemplateContainer)Container).DataItem, "Title") %>  
  6.                 <span id="b<%# this.index++.ToString() %>" class="none"><%# DataBinder.Eval(((Infragistics.Web.UI.TemplateContainer)Container).DataItem, "ID")%></span>  
  7.             </asp:Placeholder>  
  8.         </ItemTemplate>  
  9.         <Header Text="Name" />  
  10.     </ig:TemplateDataField>  
  11. </Columns>  
<Columns>
    <ig:TemplateDataField Key="Title">
        <ItemTemplate>
            <asp:Placeholder ID="Placeholder1" runat="server">
                <%# DataBinder.Eval(((Infragistics.Web.UI.TemplateContainer)Container).DataItem, "Title") %>
                <span id="b<%# this.index++.ToString() %>" class="none"><%# DataBinder.Eval(((Infragistics.Web.UI.TemplateContainer)Container).DataItem, "ID")%></span>
            </asp:Placeholder>
        </ItemTemplate>
        <Header Text="Name" />
    </ig:TemplateDataField>
</Columns>
Listing 1

This block of code creates a template column with some special elements to help power the Ajax requests.

A placeholder control is declared as a databound container so the DataBinder.Eval expressions will execute. Inside the placeholder the Title of the book is rendered to the row. The title is what is shown to the user.

Next to the Title, a span is populated with the book ID – which is hidden from the user. The purpose of the span is to contain the primary key of the record rendered to the grid. The span’s contents will be hidden from the user using a style sheet rule and will use JavaScript to read the span’s contents to get the ID value.

Getting to the container span is possible using the WebDataGrid’s client API. The current index is exposed as a method from the active cell. Therefore when a cell is activated, you can interrogate the activation data to find the current index to locate the selected item’s primary key value. You will see how this is done explicitly during the Ajax implementation below.

On line 6 of Listing 1 you will notice the following code: id="b<%# this.index++.ToString() %>". What is happening here is that the ID for each span is being assigned a unique value. The index variable is assigned in the code behind as a protected field initialized with a 0 value. This approach is a quick way to generate index values while letting the WebDataGrid’s databinding to provide the looping behavior. See Listing 2 to see this variable declared in context.

Note: Developers often like to use hidden columns to maintain state of data needed for client-site operations. Attempting to use a hidden column to hold the ID value will not work in this instance as you are using the Activation Behavior of the WebDataGrid. When Activation is enabled the user may use the tab key to advance from one active cell to the next. When a cell is active the JavaScript focus function is called in order to bring focus to the active cell. If you try to bring focus to a cell that is hidden with a stylesheet a JavaScript error is encountered as you cannot bring focus to hidden elements.

In order to hide the primary key value from the user, you must add the following style sheet entry to the header of your page:

view plaincopy to clipboardprint
  1. <style type="text/css">   
  2. .none {display:none;}   
  3. </style>  
<style type="text/css">
.none {display:none;}
</style>
Listing 2

Finally update the code behind to declare the index field and provide the grid with data:

view plaincopy to clipboardprint
  1. public partial class AJAXMasterDetail : System.Web.UI.Page   
  2. {   
  3.     protected int index = 0;   
  4.     
  5.     protected void Page_Load(object sender, EventArgs e)   
  6.     {   
  7.         if (!this.Page.IsPostBack)   
  8.         {   
  9.             this.dg.DataSource = BookRepository.Instance.GetBooks(5);   
  10.             this.dg.DataBind();   
  11.         }   
  12.     }   
  13. }  
public partial class AJAXMasterDetail : System.Web.UI.Page
{
    protected int index = 0;
 
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            this.dg.DataSource = BookRepository.Instance.GetBooks(5);
            this.dg.DataBind();
        }
    }
}
Listing 3

When you run the page and you should have a page that looks like this:

Basic List
Figure 1

Enable Activation

The next step is to enable the grid’s activation behavior. Using activation will give you client-side access to events that fire when a cell or row is activated. To enable activation, open the smart tag on the grid and select Edit Behaviors.

Behaviors Editor
Figure 2

When the behaviors window opens, check the box next to Activation and enter cellChanged as the function name for ActiveCellChanged under ActivationClientEvents. The cellChanged function will run when a new cell is made active.

Add Ajax Interaction

The next step is to add the client template and the JavaScript that will handle the Ajax interaction. While looking at the selected cell the routine will locate the primary key value then send request the detailed information on the selected item.

Client Template

When data is received from the Ajax call you will use a client template to display the data to the user.

Switch to the Source view and enter the following markup directly after the close tag for the WebDataGrid:

view plaincopy to clipboardprint
  1. <div id="details" class="none">  
  2.     <h2><a id="ttl"></a></h2>  
  3.     <table cellpadding="3" cellspacing="3"    
  4.         border="1" style="border-collapse:collapse;">  
  5.         <tr>  
  6.             <td>Author</td>  
  7.             <td id="author"></td>  
  8.         </tr>  
  9.         <tr>  
  10.             <td>Publish Date</td>  
  11.             <td id="pubDate"></td>  
  12.         </tr>  
  13.         <tr>  
  14.             <td>Price</td>  
  15.             <td id="price"></td>  
  16.         </tr>  
  17.     </table>  
  18. </div>  
<div id="details" class="none">
    <h2><a id="ttl"></a></h2>
    <table cellpadding="3" cellspacing="3" 
        border="1" style="border-collapse:collapse;">
        <tr>
            <td>Author</td>
            <td id="author"></td>
        </tr>
        <tr>
            <td>Publish Date</td>
            <td id="pubDate"></td>
        </tr>
        <tr>
            <td>Price</td>
            <td id="price"></td>
        </tr>
    </table>
</div>
Listing 4

With the application of the class of "none" the template is initially hidden from the user. When the Ajax callback is successful the template is shown to the user filled with the appropriate data in JavaScript.

JavaScript

The next step is to implement the JavaScript required to make the asynchronous calls to the server.

Return to the Source view of your ASPX page and enter the following code in the header:

view plaincopy to clipboardprint
  1. <script type="text/javascript">   
  2. var lastRow = null;   
  3.     
  4. function cellChanged() {   
  5.     var grid = $find("dg");   
  6.     var behav = grid.get_behaviors();   
  7.     var activation = behav.get_activation();   
  8.     var activeCell = activation.get_activeCell();   
  9.     var row = activeCell.get_row();   
  10.     
  11.     if (row != lastRow) {   
  12.         var id = $get("b" + row.get_index()).innerHTML;   
  13.         lastRow = row;   
  14.     
  15.         PageMethods.GetDetails(id, onSuccess, onFail);   
  16.     }   
  17. }   
  18.     
  19. function onSuccess(response) {   
  20.     $get("details").style.display = "block";   
  21.     var ttl = $get("ttl");   
  22.     ttl.innerHTML = response.Title;   
  23.     ttl.href = response.Url;   
  24.     $get("author").innerHTML = response.Author;   
  25.     $get("pubDate").innerHTML = response.PublishDateShort;   
  26.     $get("price").innerHTML = response.PriceFormatted;   
  27. }   
  28.     
  29. function onFail() {   
  30.     alert("Many bad things happened here.");   
  31. }   
  32. </script>  
<script type="text/javascript">
var lastRow = null;
 
function cellChanged() {
    var grid = $find("dg");
    var behav = grid.get_behaviors();
    var activation = behav.get_activation();
    var activeCell = activation.get_activeCell();
    var row = activeCell.get_row();
 
    if (row != lastRow) {
        var id = $get("b" + row.get_index()).innerHTML;
        lastRow = row;
 
        PageMethods.GetDetails(id, onSuccess, onFail);
    }
}
 
function onSuccess(response) {
    $get("details").style.display = "block";
    var ttl = $get("ttl");
    ttl.innerHTML = response.Title;
    ttl.href = response.Url;
    $get("author").innerHTML = response.Author;
    $get("pubDate").innerHTML = response.PublishDateShort;
    $get("price").innerHTML = response.PriceFormatted;
}
 
function onFail() {
    alert("Many bad things happened here.");
}
</script>
Listing 5

Starting at line 4 in Listing 5 notice the declaration of the cellChanged function. This is the function that is associated with the ActiveCellChanged event in the WebDataGrid Activation behavior.

When a cell is activated, the script traverses the grid’s object model by first finding the grid and then gaining access to the grid’s behavior. Once an instance of the behavior object is found then the script sets a reference to the activation behavior. The activation behavior exposes the active cell, which in turn exposes the row for the active cell.

Behavior Stack
Figure 3

Note that this relationship equates to the way you add behaviors to the grid in the markup.

Once the row of the active cell is located, the function continues in an attempt to find the selected item’s primary key value found in the hidden span tag. Line 11 checks to see if the current row is not equal to the lastRow variable. This check is necessary so unneeded Ajax calls are avoided if the user has not changed rows since the last time this function ran.

Line 12 locates the primary key value in the hidden span and sets the value aside in the id variable. In preparation for the Ajax call, the current row is set aside in the lastRow variable for later evaluation.

Finally the function calls the GetDetails function which is exposed via the ASP.NET AJAX PageMethods. The arguments to the GetDetails function include the ID as well as the names of function to run if the request is successful or if it fails.

When Things Go Right

When all goes as expected, the data is returned back to the page in the form of a serialized JSON object. With this object now in scope the function will display the client template to the user and then fill the HTML elements with the appropriate data. The following is an excerpt from Listing 5:

view plaincopy to clipboardprint
  1. function onSuccess(response) {   
  2.     $get("details").style.display = "block";   
  3.     var ttl = $get("ttl");   
  4.     ttl.innerHTML = response.Title;   
  5.     ttl.href = response.Url;   
  6.     $get("author").innerHTML = response.Author;   
  7.     $get("pubDate").innerHTML = response.PublishDateShort;   
  8.     $get("price").innerHTML = response.PriceFormatted;   
  9. }  
function onSuccess(response) {
    $get("details").style.display = "block";
    var ttl = $get("ttl");
    ttl.innerHTML = response.Title;
    ttl.href = response.Url;
    $get("author").innerHTML = response.Author;
    $get("pubDate").innerHTML = response.PublishDateShort;
    $get("price").innerHTML = response.PriceFormatted;
}
Listing 6

When Things Go Wrong

If an error is encountered during the trip back to the server, the onFail function will run. Below is the code used in this demo:

view plaincopy to clipboardprint
  1. function onFail() {   
  2.     alert("Many bad things happened here.");   
  3. }  
function onFail() {
    alert("Many bad things happened here.");
}
Listing 7

Under normal, production grade circumstances you would want to provide a graceful way to notify the user of something going wrong. Perhaps in case of a failure in this case you may want to suggest they try the request again. For now the function simply alerts the user to the fact that something went terribly wrong in the universe.

In order for the JavaScript you’ve implemented to work properly you must also enable page methods on the ScriptManager.

Update the ScriptManager

Update the ScriptManager markup to match the following markup:

view plaincopy to clipboardprint
  1. <asp:ScriptManager EnablePageMethods="true" ID="sm" runat="server" />  
<asp:ScriptManager EnablePageMethods="true" ID="sm" runat="server" />
Listing 8

WebMethod

ASP.NET page methods make it easy for you to add Ajax behavior to your page. To support the function that the JavaScript is calling when the active cell is clicked, you must add a method to the page named GetDetails that takes a book ID as an argument.

Add the following code to your codebehind:

view plaincopy to clipboardprint
  1. using System.Web.Services;   
  2. ...   
  3.   
  4. [WebMethod]   
  5. public static Book GetDetails(int id)   
  6. {   
  7.     return BookRepository.Instance.GetByID(id);   
  8. }  
using System.Web.Services;
...

[WebMethod]
public static Book GetDetails(int id)
{
    return BookRepository.Instance.GetByID(id);
}
Listing 9

Be sure to add the using statement found in line 1 to the top of your page and then add the method inside the class definition of the page.

This method simply makes a call to our test data repository and returns an instance of a book object.

Give it a Try

Run the page and click on one of the items. You should see the grid and an item’s details presented to you:

Master/Detail
Figure 4

Conclusion

The WebDataGrid has a host of behaviors that are easy to enable and gain access programmatically. In this tutorial you’ve learned to add the Activation behavior to a WebDataGrid. You used the client-side events to find resources within the grid to make an Ajax call return a JSON instance of item details. Finally, you learned to use a client template for a maintainable way of presenting asynchronous data to users.

Full Code Listing

Below are links to full code listings of this demo:

  • ASPX Markup
  • C# Codebehind

Rather Watch?

Watch the following videos to see this solution being built step-by-step.

Part 1

<object width="425" height="350"> <param name="movie" value="http://www.youtube.com/v/Ezb5z_LTZfA" /> <embed src="http://www.youtube.com/v/Ezb5z_LTZfA" type="application/x-shockwave-flash" width="425" height="350"></embed> </object>

Part 2

<object width="425" height="350"> <param name="movie" value="http://www.youtube.com/v/VbLiSxQlFrs" /> <embed src="http://www.youtube.com/v/VbLiSxQlFrs" type="application/x-shockwave-flash" width="425" height="350"></embed> </object>

  • ASP.NET
  • WebDataGrid
  • AJAX
  • Share
  • History
  • More
  • Cancel
Related
Recommended