Reviewed: Three ASP.NET DataGrid Components
- ComponentOne WebGrid
- DevExpress ASPxGrid
- Infragistics UltraWebGrid
- The Decision Grid
An increasingly important tool for an ASP.NET developer is the venerable DataGrid—the grid of data that looks like a spreadsheet or a database table. Data-driven Web sites are the norm, these days, so you need to find a way to present tables of data that your users can understand and, to some degree, manipulate.
The DataGrid that ships with ASP.NET could be more developer-friendly, as it has several limitations, but quite a few add-on components promise to fill in the gaps. I'll examine a few of those alternatives.
First, though, let's take a quick look at the ASP.NET DataGrid, to see why we need an alternative at all. It isn't that the built-in functionality doesn't work. Microsoft's DataGrid does much of what you might want, but it is more difficult than I would like.
To show you what I mean, let's examine a standard case for the DataGrid: editing a DataSet table. The goal here is to allow us to do some simple designer work and get a usable data grid to edit a single table.
Figure 1 shows how I want the grid to look: a customer table, with just a few editable columns, as well as buttons for editing and deleting rows. In addition, I want to support sorting by rows, and I want to control paging (to limit the number of results per page).
Figure 1 ASP.NET DataGrid at work
To get this far was pretty easy, using the designer. To do the data access, I simply dragged a DataSet, DataAdapter, and a DataView onto the page. We need to fill in our DataSet and make the DataBinding happen:
// Fill the DataSet theDataAdapter.Fill(theDataSet); // Data Bind as long as we are not posting back if (!IsPostBack) { DataBind(); }
Now we can run this page. However, even though we've told the grid to allow us to page, sort, edit and delete, none of it works—at least not right away.
To make it work is not hard. It just takes writing code when each feature fires an event:
void DataGrid1_PageIndexChanged(object source, DataGridPageChangedEventArgs e) { theGrid.CurrentPageIndex = e.NewPageIndex; DataBind(); } void DataGrid1_SortCommand(object source, DataGridSortCommandEventArgs e) { theView.Sort = e.SortExpression; DataBind(); } void theGrid_EditCommand(object source, DataGridCommandEventArgs e) { theGrid.EditItemIndex = e.Item.ItemIndex; DataBind(); } void theGrid_DeleteCommand(object source, DataGridCommandEventArgs e) { theView[e.Item.ItemIndex].Delete(); DataBind(); } void theGrid_CancelCommand(object source, DataGridCommandEventArgs e) { theGrid.EditItemIndex = -1; DataBind(); } void theGrid_UpdateCommand(object source, DataGridCommandEventArgs e) { // Get the data row DataRow row = theView[e.Item.DataSetIndex].Row; object dataItem = e.Item.DataItem; // Try to cast it to our customer SampleDataSet.CustomersRow customer = row as SampleDataSet.CustomersRow; // If the customer is correct if (customer != null) { // Save the items customer.CompanyName = ((TextBox)e.Item.Cells[1].Controls[0]).Text; customer.ContactName = ((TextBox)e.Item.Cells[2].Controls[0]).Text; customer.ContactTitle = ((TextBox)e.Item.Cells[3].Controls[0]).Text; customer.Phone = ((TextBox)e.Item.Cells[4].Controls[0]).Text; customer.City = ((TextBox)e.Item.Cells[5].Controls[0]).Text; customer.Region = ((TextBox)e.Item.Cells[6].Controls[0]).Text; } theGrid.EditItemIndex = -1; DataBind(); }
Granted, this is not a lot of code, but it is code. (And every line of code is an opportunity to create a bug.) It's a straightforward operation, so I expected this to be more automatic.
I want a data grid that is friendly to the design-time environment, and also has a set of key features, including hierarchical display, user controlled column layout, built-in dual direction sorting (with image arrows, if possible), and grouping. Is that too much to ask for?
So I went shopping for alternatives. I tested three of the most popular DataGrids: ComponentOne LLC's WebGrid, Developer Express Inc.'s ASPxGrid and Infragistics Inc.'s UltraWebGrid. (I also planned to test FarPoint Technologies, Inc.'s Spread, but was unable to get it working. I hope it can be reviewed soon.)
To judge these DataGrids, I created a set of requirements for my not-too-difficult typical scenario. (If you want to follow along, the code for all the examples in this article is available here:datagridexamples.zip.) My criteria include simple database table editing, the features I described above, the quality of the documentation (documentation is everything, with a tool like this, as it shouldn't take longer to learn the tool than to write the code from scratch), and the price of the software. In the big picture, the cost of the component is not very important. When you look at cost, against getting your development staff to write the same functionality, components are very cheap.
ComponentOne WebGrid
WebGrid is a full-featured, intuitive part of a much larger suite of tools from ComponentOne. This suite, called Studio Enterprise, contains components which work with both ASP.NET and Windows Forms.
This control looks and feels the most like the ASP.NET data grid, so if you want to change relatively little about the way you're writing code (or you have a lot of DataGrid code to replace), this may be the best option.
WebGrid both looks and acts much like the ASP.NET DataGrid. Editing is handled on a row-by-row basis.
To get to the basic functionality, you need to write a handful of code:
void C1WebGrid1_PageIndexChanged(object sender, C1PageChangedEventArgs e) { C1WebGrid1.CurrentPageIndex = e.NewPageIndex; DataBind(); } void C1WebGrid1_SortCommand(object sender, C1SortCommandEventArgs e) { theView.Sort = e.SortExpression; DataBind(); } void C1WebGrid1_EditCommand(object source, C1CommandEventArgs e) { C1WebGrid1.EditItemIndex = e.Item.ItemIndex; DataBind(); } void C1WebGrid1_DeleteCommand(object source, C1CommandEventArgs e) { theView[e.Item.ItemIndex].Delete(); DataBind(); } void C1WebGrid1_CancelCommand(object source, C1CommandEventArgs e) { C1WebGrid1.EditItemIndex = -1; DataBind(); } void C1WebGrid1_UpdateCommand(object source, C1CommandEventArgs e) { // Calculate the DataSetIndex since they control doesn't support it int dataSetIndex = e.Item.ItemIndex + (C1WebGrid1.CurrentPageIndex * C1WebGrid1.PageSize); // Get the data row DataRow row = theView[dataSetIndex].Row; object dataItem = e.Item.DataItem; // Try to cast it to our customer SampleDataSet.CustomersRow customer = row as SampleDataSet.CustomersRow; // If the customer is correct if (customer != null) { // Save the items customer.CompanyName = ((TextBox)e.Item.Cells[1].Controls[0]).Text; customer.ContactName = ((TextBox)e.Item.Cells[2].Controls[0]).Text; customer.ContactTitle = ((TextBox)e.Item.Cells[3].Controls[0]).Text; customer.Phone = ((TextBox)e.Item.Cells[4].Controls[0]).Text; customer.City = ((TextBox)e.Item.Cells[5].Controls[0]).Text; customer.Region = ((TextBox)e.Item.Cells[6].Controls[0]).Text; } C1WebGrid1.EditItemIndex = -1; DataBind(); }
This code is identical to the code we put in the ASP.NET DataGrid, except that the event handlers pass ComponentOne argument types. The database editing is on par with ASP.NET, no more, no less.
Figure 2 ComponentOne WebGrid
But WebGrid doesn't simply duplicate what you get from the built-in ASP.NET DataGrid. It is packed with impressive functionality: sorting (that includes sorting markers and automatic support for descending), sizable and orderable columns, and grouping support.
On the downside, it was downright difficult to find good references to some of those features, such as adding value lists and page by demand (where the actual loading from the database only happens incrementally). While the documentation is adequate, I would have liked to see better MSDN integration; for example, I could not filter for only ComponentOne's documentation, which made searching more laborious.
The biggest reason to use the ComponentOne WebGrid is if you are already using the ASP.NET grid and want an in-place replacement with some additional features.
You can buy the ComponentOne WebGrid control all by itself for $399. The control is also part of the company's ASP.NET set of controls for $649, or every .NET control they have for $899. There are no runtime fees.