navigation
 Tuesday, December 04, 2007

I recently wrote a new feature that would detect changes to an item being edited and show a modal dialog listing all other items that would be affected by the change. The problem was that in many cases, the number of affected items could be quite large, causing a significant delay before the dialog would appear. I decided that I wanted to show the dialog immediately, then begin loading the potentially large dataset afterwards while displaying a loading icon.

The Basics

The basics of how to do this are covered on the Telerik website:

  1. On the client, initiate the asynchronous callback using the RadGrid's AjaxRequest method:
    <%= rg.ClientID %>.AjaxRequest( "<%= rg.UniqueID %>", "Rebind" );
  2. On the server, override and handle the RaisePostBackEvent method:
    protected override void RaisePostBackEvent( IPostBackEventHandler sourceControl, string eventArgument )
    {
        base.RaisePostBackEvent( sourceControl, eventArgument );
        if ( eventArgument == "Rebind" )
            rg.Rebind();
    }

This all worked as expected as long as the grid was already bound to some data when the AjaxRequest was made, and the AjaxRequest wasn't executed during page loading, but when I tried doing the same thing with an unbound grid on page load, it didn't work as expected; performing the AjaxRequest before the page finished loading caused script errors, and performing the AjaxRequest with an unbound grid filled the grid, but didn't show the loading icon.

Getting The Timing Right

The first problem was how to get the AjaxRequest going at the first possible moment with a minimum of code. Simply adding the call at the end of the page didn't work, nor did handling the grid's client-side OnGridGreated event. Ultimately, I found that attaching a handler to the browser document's onload event worked:

<script type="text/javascript">
function rg_rebind()
{
    <%= rg.ClientID %>.AjaxRequest( "<%= rg.UniqueID %>", "Rebind" );
}

window.attachEvent( "onload", rg_rebind );
</script>

Getting The Loading Template to Appear

Now the grid was starting empty, then loading with data after the dialog appeared, but the grid was just a gray rectangle with no loading icon! Some experimentation revealed that the loading icon would only appear if the grid was already bound to some data. Since binding to the actual data I wanted to load asynchronously would defeat the whole point of the exercise, I decided I needed to bind to an empty dataset that contained only the schema of the dataset I would load again later. There are many possible ways to do this, but I decided on a T-SQL solution, since it would allow me to keep the no-data "schema" query and the potentially large query together in one place. Minimizing duplicate code means minimizing code maintenance! I wrote a stored procedure like this one to fuel my grid (this example uses the AdventureWorks DB):

create procedure Sales.SalesOrderDetail_SelectBy_SalesOrderID
  @SalesOrderID int,
  @SchemaOnly bit
as
set nocount on

declare @n tinyint
set @n = case @SchemaOnly when 1 then 0 else 100 end

select top( @n ) percent *
from Sales.SalesOrderDetail
where SalesOrderID = @SalesOrderID

When @SchemaOnly = 1, the top 0% rows are selected; otherwise, everything is returned. After configuring the grid to bind to the "schema only" result set on initial load and to the "all data" version on postback, I got the result I wanted: a dialog that appears immediately with column headers only, then loads asynchronously while displaying the loading icon. I hope this article saves you some of the time and effort it took me.

Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, i, strike, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview