Building a DataGrid Helper Control for ASP.NET 1.x: Part 3
 
Published: 09 Jul 2004
Unedited - Community Contributed
Abstract
In the first two parts of this series, we built a DataGrid helper control that can be used to develop a data access page with sorting, paging, deleting, and updating capabilities without writing a single line of code. In this part, we will discuss how to customize DataGrid columns using custom columns.
by Li Chen
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 32583/ 69

Introduction

[Download Code]

In Part 1 and Part 2 of this series, we successfully built the DataGridHelper control that can be used to develop a data access page with sorting, paging, deleting, and updating capabilities without writing a single line of code.  I have had too much fun to stop now. In Part 3, we will address another limitation of DataGrid and DataGridHelper control--custom columns.

In ASP.NET 1.x, the easiest way to create custom column is by using the TemplateColumn. The TemplateColumn supports one-way databinding to display the data. The update code is not exactly pretty, as seen in a Microsoft QuickStart sample, because we have to find the control from the controls collection of the table cell and extract the value from the control. The up-coming ASP.NET 2.0 will support two-way binding in GridView templates.  For ASP.NET 1.x, Marcie Robillard’s MSDN article discussed an excellent idea of custom columns. The code related to the column is packaged in the custom column class instead of an aspx page, making it reusable. Although it takes some up-front cost to develop, custom columns are easier to use than TemplateColumn. The Metabuilders site has a few great custom columns. In this article, we will extend the idea further by giving the custom column class the responsibility to extract user input. We will also extend the DataGridHelper control to work with custom columns.

We will start by creating the necessary interface for the DataGridHelper control to work with custom columns. We will then build two custom columns that support such an interface. We will also discuss how to extend an existing custom column so we can use the DataGridHelper control with any custom column. We will finally demonstrate how to use the custom columns and conclude this article.

Let's define the interface first.

Enhancing the DataGridHelper Control to Support Custom Columns

[Download Code]

Let us first examine how the DataGridHelper control extracts user input from a bound column:

BoundColumn bc = (_dataGrid.Columns[i] as BoundColumn);
if (bc != null)
{
 name = bc.DataField;
if (bc.ReadOnly)
 {
  val = e.Item.Cells[i].Text;
 }
 else
 {
  val = ((TextBox)e.Item.Cells[i].Controls[0]).Text;
 }
 col[name] = val;
}

The code contains the knowledge of the BoundColumn because we know how it works. However, we cannot expect the DataGridHelper control to have the knowledge all existing custom columns and all future custom columns; we cannot keep changing the code of DataGridHelper to add the knowledge of new custom columns. Thus our first step is to define an interface for DataGridHelper and custom columns to work together:

public interface IDataGridColumn
{
 void GetValues(TableCell cell, Hashtable col);
}

All custom columns designed to work with DataGridHelper control must implement this interface. The interface has a single method called GetValues. The DataGridHelper will pass a TableCell object and a Hashtable object to the custom column. The custom column class is responsible for extracting the input from the TableCell and adds the field/value pair to the Hashtable. This design can work with custom columns that contain more than one input control. For example, a phone number column could have a control for the area code and another control for the phone number; a zip code column could have a control for the zip code and another control for the zip extension. Since the custom columns are responsible for extracting the inputs, we only need to add the following code in the _dataGrid_UpdateCommand function of DataGridHelper to support custom columns:

IDataGridColumn ic = _dataGrid.Columns[i] as IDataGridColumn;
if (ic != null)
{
 ic.GetValues(e.Item.Cells[i], col);
}

That is it. It is so simple! Next, we will introduce two custom DataGrid columns that implement IDataGridColumn interface.

Creating Custom DataGrid Columns

[Download Code]

We included two custom DataGrid columns in this article: the CheckBoxColumn and the DropDownColumn. The custom DataGrid columns included in this article were created in a similar way to the custom columns on the MetaBuilders site and in Marcie Robillard’ MSDN article. We encourage you to read Marcie Robillard’s MSDN article if you are interested in creating custom columns. In this article, we will focus on the feature and the difference in our implementation.

The CheckBoxColumn is a very simple class and has only two properties:

DataField The data field to bind to.
ReadOnly The CheckBoxColumn always render data as CheckBox. The CheckBox is only enabled when the item is an edit item and the ReadOnly property is equal to false.

The design of DropDownColumn is somewhat different to the design of Marcie Robillard and MetaBuilders. Both the Marcie Robillard version and the MetaBuilders version expose a DataSource property for users to populate the data source. Since DataSource is not the only way to populate a DropDownList control, we decide to expose the underlying DropDownList control instead so that users can populate it in any way of their choice. The other important difference is the optimization we made for the population of the DropDownList. Since the DropDownList is used only in edit mode, we should not populate the DropDownList until we need to. For this reason, DropDownColumn exposes the LoadDropDownList event in which we can populate the DropDownList. If we care more about the simplicity than optimization, we could still populate the DropDownList in the Page_Int or Page_Load event using the DropDownList property of the DropDownColumn class. The following is the complete list of DropDownColumn properties:

DataField  The data field to be displayed. It is also the data field used for to populate the name/value pair used for update if the DataValueField is not supplied. This field is required.
DataFormatString  Used to format the data field displayed.
DataValueField  If supplied, the DataValueField and selected value of the DropDownList would be used to form the name/value pair for update.
DropDownList Used to access the underlying DropDownList. Note that for optimization purpose, the actually DropDownList object is only instantiated when it is necessary to instantiate the DropDownList, or this property is accessed, whichever occurs first.
ReadOnly  If the value of this property is true, the DropDownList is disabled.

Let’s first take a look of the implement the IDataGridColumn interface in the CheckBoxColumn:

public void GetValues(TableCell cell, Hashtable col)
{
 bool val = ((CheckBox)cell.Controls[0]).Checked;
 col[_dataField] = val;
}

We simply extract the value of the CheckBox control.

Now let us take a look of the implement the IDataGridColumn interface in the DropDownColumn:

public void GetValues(TableCell cell, Hashtable col)
{
 string name;
 object val;
   
 if  (this.DataValueField == null || this.DataValueField == "")
 {
  name = this.DataField;
  val = _ddl.SelectedItem.Text;
 }
 else
 {
  name = this.DataValueField;
  val = _ddl.SelectedItem.Value;
 }
 col[name] = val;
}

Note that we extract the text or value of the SelectedItem depending on whether the DataValueField property is set.

Next, we will discuss how to use an arbitrary custom DataGrid column with the DataGridHelper control.

Using Third-Party Custom DataGrid Columns with the DataGridHelper Control

[Download Code]

There are two ways to use a DataGrid column that does not implement the IDataGridColumn interface with the DataGridHelper control. If the source code is available, we can add the implementation for the IDataGridColumn interface. If the source code is not available, we could create a new class that is inherits from the custom DataGrid column class and implements the IDataGridColumn interface, as shown in the following example:

public class MyBoundColumn: ThirdPartyBoundColumn, IDataGridColumn
{
 public void GetValues(TableCell cell, System.Collections.Hashtable col)
 {
  //Implement the code to extract the input here
 }
} 

In the next section, we will show the use of the custom columns through an example.

Using the DataGridHelper Control with Custom Columns

[Download Code]

The DataGridHelper.aspx page demonstrates the use of DataGridHelper control with custom columns. A live demo can be accessed at http://www.dotneteer.com/projects/DataGridHelper/v3/DataGridHelperTest.aspx.

The custom columns are created and added to the DataGrid in the page_event as shown below:

private void DataGridHelperTest_Init(object sender, System.EventArgs e)
{
 DropDownColumn ddcSupplier = new DropDownColumn();
 ddcSupplier.DataField = "CompanyName";
 ddcSupplier.DataValueField = "SupplierID";
 ddcSupplier.HeaderText = "Supplier";
 ddcSupplier.SortExpression = "CompanyName";
 ddcSupplier.LoadDropDownList +=new LoadDropDownListEventHandler(ddcSupplier_LoadDropDownList);
 dataGridProducts.Columns.AddAt(4,ddcSupplier); 

 DropDownColumn ddcCategory = new DropDownColumn();
 ddcCategory.DataField = "CategoryName";
 ddcCategory.DataValueField = "CategoryID";
 ddcCategory.HeaderText = "Category";
 ddcCategory.SortExpression = "CategoryName";
 ddcCategory.LoadDropDownList +=new LoadDropDownListEventHandler(ddcCategory_LoadDropDownList);
 dataGridProducts.Columns.AddAt(5,ddcCategory); 

 CheckBoxColumn cbcDiscontinued = new CheckBoxColumn();
 cbcDiscontinued.DataField = "Discontinued";
 cbcDiscontinued.HeaderText = "Discontinued";
 cbcDiscontinued.SortExpression = "Discontinued";
 dataGridProducts.Columns.AddAt(11,cbcDiscontinued);
}

Note that it is possible to add the custom columns declaratively using tags. However, that would break the design-time behavior of the DataGrid control because it does not recognize the custom columns for the two DropDownColumn classes. Note that we also attached event handlers to the LoadDropDownList event of the DropDownColumn class. Since the two event handlers are nearly identical, we only show one below:

private void ddcCategory_LoadDropDownList(object Sender, LoadDropDownListEventArgs e)
{
 DropDownList ddl = e.DropDownList;
 if (sqlConnection.State != ConnectionState.Open)
  sqlConnection.Open();

 SqlCommand cmd = new SqlCommand("select CategoryID, CategoryName from Categories",sqlConnection);
 SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
 ddl.DataTextField = "CategoryName";
 ddl.DataValueField = "CategoryID";
 ddl.DataSource = dr;
 ddl.DataBind();
}

In the next section, we conclude this article.

Conclusion

[Download Code]

In this article, we have shown a way to use custom columns to enhance the functionality of a data access page based on the DataGrid control. We have also designed a generic way for DataGridHelper to work with custom columns. Although this method is not quite as easy to use as the two-way data-binding promised in the upcoming ASP.NET 2.0, it is a more reusable way to extend the functionality of the DataGrid control.

Resources:



User Comments

Title: how to insert   
Name: eyal
Date: 2005-06-09 4:02:12 AM
Comment:
i wont to insert to grid in a way that the colomn will open in a visual stae in the grid mach like the edit command if you can help me
thenks
Title: Building a DataGrid Helper Control for ASP.NET 1.x: Part 3   
Name: greg
Date: 2005-04-30 12:07:57 PM
Comment:
he control is very cool.
I have a question regarding the DataGridHelper control:
1. why do we need a DataGridHelperconnector component? the web component is disappeared in asp.net 2.0

2. can we set the properties dataAdapter, datagrid to browsable instead of using the connector? so that we can set these properties at design time.

I'm lokking forward to your answer, Thanks
Title: Re: Small bug   
Name: Li Chen
Date: 2004-12-22 12:12:44 PM
Comment:
I would like to thank Robert for pointing out the bug in part 2 of the article. The bug was discovered during the writing of the part 3 of this series and fixed. Readers are urged to use the code from part 3.
Title: Small bug   
Name: Robert Storrs
Date: 2004-12-01 2:34:39 PM
Comment:
Great Article. One of the best I have read in some time.

I did find a small bug and added the following line as line 134 in the DataGridHelperConnector.cs (in version 2)

134 if(_dataGridHelper.DataGrid != _dataGrid)
_dataGridHelper.DataGrid = _dataGrid;

Without this check, the program creates two event handlers for the SortCommand. This results in the new sort order always being DESC. It also caused multiple reloading of the grid.
Title: Everybody speaks C#   
Name: Shain
Date: 2004-09-14 9:06:50 PM
Comment:
Any computer science program should know the basics of languages similiar to Java, C++, C, or the like. It is not very hard to convert C# code to VB code and since this article really explores Data Structures & Algorithms approaches it is pretty easy to convert. You should study this article, and if you need VB, try to write the code yourself. There is probably an advantage to having this as C# code -- although the CLR may not care.
Title: love it   
Name: ben
Date: 2004-09-14 7:09:11 AM
Comment:
love it
Title: Building a DataGrid Helper Control for ASP.NET 1.x: Part 3   
Name: Peter Ho
Date: 2004-09-12 12:29:05 AM
Comment:
A great series of articles, Mr. Chen. Thanks!
Title: Building a DataGrid Helper Control for ASP.NET 1.x: Part 3   
Name: T. freeman
Date: 2004-08-16 11:07:09 AM
Comment:
Excellent article - well written, good detail. Thanks!
Title: Building a DataGrid Helper Control for ASP.NET 1.x: Part 3   
Name: Li Chen
Date: 2004-07-20 12:53:03 PM
Comment:
Sam,

The download does include the VB version of the DataGridHelperTest project.

Li
Title: Building a DataGrid Helper Control for ASP.NET 1.x: Part 3   
Name: Sam Richardson
Date: 2004-07-20 9:27:49 AM
Comment:
It would be even better if there was some vb.net code to go with it - not everyone speaks C#.

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 5:43:52 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search