A web page with a data bound
GridView
control can take a long time to load. The page is not rendered until
all the controls are, and the GridView cannot render before data has
been retrieved from the database. So, let’s load the GridView
asynchronous and make the page load faster and the perceived speed
greater.
This little trick is actually very simple and it
involves the built-in client callback feature of ASP.NET. Even though
I’m not a big fan of that particular feature, it can be quite handy
from time to time. The best part of this is that you don’t have to
change much to your existing code.
Web page
On the webpage that hosts the GridView control, you have to make 2 small changes.
Step 1. Encapsulate the GridView
The GridView control has to be encapsulated by an HTML control
with an id attribute, so that it can be referenced by JavaScript. That
is because the GridView does not render when no data is bound to it.
"grid">
Loading...
"Server" ID="gvAsync" />
Step 2. Add a JavaScript
Then a JavaScript is needed to load the rendered and data bound
GridView to the HTML control we added in step 1. Place the JavaScript
below the GridView’s surrounding div tag.
Code-behind
In the code-behind file there are three small steps to perform.
Step 3. Implement ICallbackEventHandler
We need to implement the interface to
turn on the client callback feature.
public partial class asyncgridview : System.Web.UI.Page, ICallbackEventHandler
Step 4. Bind the call back reference
The literal control placed in the JavaScript function in step 2
has to contain the client callback reference. Add the following to the
Page_Load.
if (!Page.IsCallback)
ltCallback.Text = ClientScript.GetCallbackEventReference(this, "'bindgrid'", "EndGetData", "'asyncgrid'", false);
Step 5. Bind the grid and return the rendered HTML
To finish the asynchronous loading we have to implement the two methods that are defined by the
ICallbackEventHandler
interface we implemented in step 3. One of the methods binds a
DataTable to the GridView and renders the control. The second returns
the rendered HTML to the JavaScript method we defined in step 2.
private string _Callback;
public string GetCallbackResult()
{
return _Callback;
}
public void RaiseCallbackEvent(string eventArgument)
{
DataTable table = RetrieveDataTableFromDatabase();
gvAsync.DataSource = table;
gvAsync.DataBind();
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
gvAsync.RenderControl(new HtmlTextWriter(sw));
_Callback = sw.ToString();
}
}
You can use your present data binding method to bind the
GridView. The important part is that the GridView is data bound before
the RaiseCallbackEvent method renders the control.
The same technique can be used for all the data control such as the Repeater, FormView and DataList.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="asyncgridview.aspx.cs" Inherits="asyncgridview" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Async GridView</title>
</head>
<body>
<form id="form1" runat="server">
<div id="grid">
<span>Loading...</span>
<asp:GridView runat="Server" ID="gvAsync" />
</div>
<script type="text/javascript">
function EndGetData(arg)
{
document.getElementById("grid").innerHTML = arg;
}
setTimeout("<asp:literal runat="server" id="ltCallback" />", 100);
</script>
</form>
</body>
</html>
using System;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class asyncgridview : System.Web.UI.Page, ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(5000);
if (!Page.IsCallback)
ltCallback.Text = ClientScript.GetCallbackEventReference(this, "'bindgrid'", "EndGetData", "'asyncgrid'", false);
}
private DataTable RetrieveDataTableFromDatabase()
{
DataTable table = new DataTable();
table.Columns.Add("Product", typeof(string));
table.Columns.Add("Price", typeof(float));
table.Rows.Add("Hat", 16);
table.Rows.Add("Jacket", 234);
table.Rows.Add("Socks", 35);
return table;
}
#region ICallbackEventHandler Members
private string _Callback;
public string GetCallbackResult()
{
return _Callback;
}
public void RaiseCallbackEvent(string eventArgument)
{
DataTable table = RetrieveDataTableFromDatabase();
gvAsync.DataSource = table;
gvAsync.DataBind();
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
gvAsync.RenderControl(new HtmlTextWriter(sw));
_Callback = sw.ToString();
}
}
#endregion
}
0 comments: