This is a followup to my post on creating a DropDownField for the GridView control. Just a couple of tips for anyone else who might be developing custom columns for the GridView. If you don't care about customizing the GridView, don't bother reading this.
Tip #1 - Respect the Page Lifecycle
The distinction between the two methods I mentioned previously, InitializeDataCell and OnDataBindField, was vague to me at first. It didn't seem to matter which method I used for creating controls to insert into the GridView. Now, I'm a little wiser. You want to instantiate your controls in InitializeDataCell so that their change events will fire, if you want and instantiate them in OnDataBindField it will be to late. Additionally, you will not be able to access the bound data until the DataBinding event, thus the need for the second method.
Tip #2 - Beware of Adding Members to DataControlFieldCell
There is only one instance of field defined in a GridView regardless of the number of rows. When I first attempted to create a custom field, I inherited from DataControlFieldCell and added a private member of type TextBox called EditControl. I set EditControl in InitializeDataCell to a new TextBox, and set the .Text property in OnDataBindField. My first test only had one row of data in the GridView and everything seemed to work. My second test had many rows of data, and it no longer worked. I discovered that my EditControl field was being shared across every row, because there is only one instance of the each field.
The solution was to do something like this:
protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
cell.DataBinding += OnDataBindField;
if ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal)
{
cell.Controls.Add(new TextBox());
}
}
and
protected override void OnDataBindField(object sender, EventArgs e)
{
DataControlFieldCell cell = (DataControlFieldCell) sender;
string myBoundData = GetValue(cell.NamingContainer).ToString();
if ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal)
{
(cell.Controls[0] as TextBox).Text = myBoundData;
}
else
{
cell.Text = myBoundData;
}
}
Posted
09-20-2006 8:41 PM
by
Christopher Bennage