This article details the development of an AJAX-enabled grid using ICallbackEventHandler, with operations which include sorting, paging and page length change. I will work through the code in sequence, but it may help to download to the entire code sample here
The basic features of the gird are as follows (All operations are asynchronous)
In this example we will use one of the most powerful features of ASP.Net - RenderControl.
Using this method we are able to access the HTML of a control. To do this we will have to also use HtmlTextWriter and StringWriter as follows
e.g.
using (StringWriter sw = new StringWriter())
{
HtmlTextWriter htw = new HtmlTextWriter(sw);
_grid.RenderControl(htw);
htw.Flush();
string result = sw.ToString();
}
The result string will contain the HTML format of the grid control. We will now convert the grid control to HTML after binding the data.
We will start by developing the UI and code in following steps:
<div id="Gridview" >
<asp:GridView EnableViewState="false" runat="server" id="_grid" OnRowDataBound="_grid_RowDataBound" AllowPaging="True" >
</asp:GridView>
<br />
</div> Change page length to --
<asp:DropDownList ID="ddl" runat="server">
</asp:DropDownList>
Please note that RowDataBound event of the grid has been activated.
public DataTable _sampleData
get {
DataTable dt = (DataTable)ViewState["DataTable"];
if(dt == null)
dt = new DataTable();
dt.Columns.Add(new DataColumn("Contact Name",typeof(string)));
dt.Columns.Add(new DataColumn("Company Name", typeof(string)));
dt.Columns.Add(new DataColumn("City", typeof(string)));
dt.Columns.Add(new DataColumn("Country", typeof(string)));
dt.Rows.Add(new object[] { "Maria Anders" ,"Alfreds Futterkiste","Berlin","Germany"});
dt.Rows.Add(new object[] { "Ana Trujillo" ,"Emparedados y helados ","México D.F.","Mexico"});
dt.Rows.Add(new object[] { "Antonio Moreno", "Antonio Moreno Taquería", "México D.F.","Mexico" });
ViewState["DataTable"] = dt;
return dt;
In the above code we have used ViewState instead of a Session variable.
i.e. ViewState["DataTable"] = dt;
This will preserve the table for that page. Using Session variable the table would be available throughout the website, but using ViewState the table will only be available for that page.
To bind this table to the GridView we simply use _grid.DataSource = _sampleData;
DataView dv = _sampleData.DefaultView;
result = "";
dv.Sort = Argument;
_grid.DataSource = dv;
_grid.PageSize = Convert.ToInt16(pageLength);
_grid.DataBind();
renderGrid(_grid);
private void changePage(string Argument , string pageLength)
_grid.DataSource = _sampleData;
_grid.PageIndex = Convert.ToInt16(Argument);
private void changePageLength(string Argument, string pageLength)
_grid.PageSize = Convert.ToInt16(Argument);
//pageLength is not used
private void renderGrid(GridView _grid)
result = sw.ToString();
The names of the above functions indicates their functionality, the second parameter of the first three functions is “pageLength” this is the value of the dropdown list
JavaScript functions are as follows:
function UpdateGrid(args)
args = args + "$" + window.document.getElementById('ddl').value;
<%= ClientScript.GetCallbackEventReference(this,"args", "ShowResult", null) %>
After rendering, if we open the source of the page; above function will appear as
WebForm_DoCallback('__Page',args,ShowResult,null,null,false)
When we want to do a Callback, we are actually firing an event which is related to the Webform. Therefore the UpdateGrid(args) function needs to be placed in the <form> tag, otherwise we will get a JavaScript error.
We register this function by using Page.ClientScript.RegisterClientScriptBlock so the function will appear in <form></form> tag only.
function ShowResult(eventArgument,context)
window.document.getElementById('Gridview').innerHTML = eventArgument;
This function will be fired after server sends a response back to client, thus this function will handle the server response. We have simply put the response as innerHTML of the Div tag. The innerHTML contains the HTML of the updated grid.
The server-Side functions are as follows
return result;
This function simply returns the result which we have put as innerHTML in the ShowResult function. public void RaiseCallbackEvent(string eventArgument)
string[] args = eventArgument.Split('$');
if (args[0] == "sort") { sortGrid(args[1], args[2]); }
else if (args[0] == "changePage") { changePage(args[1], args[2]); }
else if (args[0] == "changePageLength") { changePageLength(args[1], args[2]); }
In this function the eventArgument will appear as “changePage$1$10” or “sort$1$10” or “changePageLength$1$10” or “sort$Contact Name Asc$10” or “sort$Contact Name Desc$10” in the rendered page
If we split this on “$”, we will get
(In changePageLength we don’t need args[2]; I have kept is just to simplify the code)
In RaiseCallbackEvent we have called the function which we have decleared in POINT 3, each function in point 3 will do the respective action and return a HTML string of the Grid.
if (!IsPostBack)
ddl.Items.Add("10");
ddl.Items.Add("20");
ddl.Items.Add("30");
ddl.Attributes.Add("onchange", "javascript:UpdateGrid('changePageLength$' + this.value);");
[At this point if we compile the code we will able to chage the page length ]