This article is also maintained on my blog.
Introducing the DeleGrid
The DeleGrid
is a control derived from the ASP.NET GridView
, that delegates its data retrieval back out of the control. This allows the developer full control over the records that are retrieved, thus allowing proper paging to be implemented using whatever collection type is preferred.
Background
The DeleGrid
came about because I wanted a nice way of implementing paging using NHibernate
without having the grid
know about it. I really didn't want NHibernate
to leave my data layer, so I needed a nice way of the grid
calling my DAL with the paging parameters.
Using the DeleGrid
After getting the source or assembly and doing the usual song-and-dance, add a reference to the control to your page:
<%@ Register Assembly="JAGregory.Controls.DeleGrid"
Namespace="JAGregory.Controls" TagPrefix="jag" %>
Then create an instance of the control, turning the paging on and setting the correct page size:
<jag:DeleGrid ID="grid" runat="server" AllowPaging="true" PageSize="4" />
Now you have a control set up, however it still won't bind correctly. So, you need to attach the event handlers in the code-behind.
protected override void OnInit(EventArgs eventArgs)
{
base.OnInit(eventArgs);
grid.TotalRecordCountRequest += delegate {
};
}
Starting with the TotalRecordCountRequest
, this event is raised when the grid
needs to know how many records in total your grid
is going to be displaying. This number is the cumulative count of all the pages. I'm going to use a simple repository pattern to factor away my DAL logic.
The OnInit
method is now:
protected override void OnInit(EventArgs eventArgs)
{
base.OnInit(eventArgs);
ProductRepository repos = new ProductRepository();
grid.TotalRecordCountRequest += delegate {
return repos.GetTotal();
};
}
Now your grid
knows how many records it has overall, however we still haven't told it how to actually get the data. Now we need to put the code in the PageDataRequest
handler. This event is raised when the grid
needs a new page of data. This will get called once on initial data-bind, then again every time you change the page (or sort etc.).
The OnInit
method is now:
protected override void OnInit(EventArgs eventArgs)
{
base.OnInit(eventArgs);
ProductRepository repos = new ProductRepository();
grid.TotalRecordCountRequest += delegate {
return repos.GetTotal();
};
grid.PageDataRequest += delegate(object sender, DataRequestEventArgs e) {
return repos.GetRange(e.Start, e.Size);
};
}
The event-handler receives an instance of DataRequestEventArgs
, which contains the start index of the current page of data, and the number of records in a page. It also contains a SortField
and SortDirection
, used when sorting is enabled on the grid
. However, we aren't utilising them in this example.
Finally we just need to bind the grid
on page load. We don't re-bind the grid
on post-back, since it is handled internally in the DeleGrid
.
protected override void OnLoad(EventArgs eventArgs)
{
base.OnLoad(eventArgs);
if (!IsPostBack)
grid.DataBind();
}
That’s all there is to it!
You don't need to use delegates, the normal event-handler syntax is fine (and probably preferred for larger examples). I just did it this way for brevity’s sake.
Further Reading...
Testing
I've written a small number of tests that cover the implementation of the grid
as best as I can. There was only so-far I was willing to go to test the control, as it’s heavily tied to the ASP.NET implementation. This can get pretty messy for testing without using something like NUnitASP
, which was a little too much for one control. I've got coverage of about 85% of the code, which I'd say is pretty reasonable anyway.
Sorting
As mentioned above, you can implement sorting in your handlers by accessing the SortField
and SortDirection
properties of the event arguments.
DeleGrid.AlwaysRequestTotal Property
By default, the DeleGrid
only requests the total number of records on the initial data-bind. However if you see this as being a problem (such as with rapidly changing data-sets), you may want to set this property to true
so it refreshes the total on every data-bind.
Open Source
The DeleGrid
is open-source under the new BSD License. Read the license for what you're allowed to do.
The source is also accessible from Subversion here (using user jagregory-read-only).
History