Extending DataControlField – EditableButtonField

It turns out that once you start extending DataControlField, you never turn back.  I have discovered joy in reducing code duplication and creating reusable components by converting common GridView tasks into new DataControlFields. Here’s another fun one: EditableButtonField.

A “normal” ButtonField is a read-only control which has no built-in behavior when the row is being edited.  With the EditableButtonField control, it will convert to a TextBox and provide immediate access to the DataTextField element.  Nifty!

Note that this control simply extends ButtonField rather than extending the full DataControlField.  Also note that I am assuming a ButtonType of “Link” and this would probably explode into itty bitty bits if you tried a Button.


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace JoeDonahue.resources {
public class EditableButtonField : ButtonField {

private Boolean inEditMode;

public override void InitializeCell(DataControlFieldCell cell,
DataControlCellType cellType, DataControlRowState rowState, int rowIndex) {
base.InitializeCell(cell, cellType, rowState, rowIndex);

switch (cellType) {
case DataControlCellType.DataCell:
this.InitializeDataCell(cell, rowState);
case DataControlCellType.Footer:
this.InitializeFooterCell(cell, rowState);
case DataControlCellType.Header:
this.InitializeHeaderCell(cell, rowState);

protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) {

cell.DataBinding += new EventHandler(OnDataBindField);

this.inEditMode = (rowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0;

if (inEditMode) {
TextBox t = new TextBox();
} else {
// Default behavior is OK

protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState) {

protected void InitializeFooterCell(DataControlFieldCell cell, DataControlRowState rowState) {

protected virtual void OnDataBindField(object sender, EventArgs e) {
TableCell cell = (TableCell)sender;
IDataItemContainer container = (IDataItemContainer)cell.NamingContainer;
object boundvalue = GetBoundValue(container);
String selectedValue = boundvalue.ToString();

/* Set the corresponding text or selectedValue */
if (inEditMode) {
object dataItem = DataBinder.GetDataItem(container);
boundvalue = DataBinder.GetPropertyValue(dataItem, DataTextField);
selectedValue = boundvalue.ToString();

TextBox t = (TextBox)cell.Controls[0];

if (selectedValue != null && selectedValue.Length > 0)
t.Text = selectedValue;

} else {
LinkButton l = (LinkButton)cell.Controls[0];
l.Text = selectedValue;


object GetBoundValue(IDataItemContainer controlContainer) {
object dataItem = DataBinder.GetDataItem(controlContainer);
return DataBinder.GetPropertyValue(dataItem, DataTextField);

public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly) {

base.ExtractValuesFromCell(dictionary, cell, rowState, includeReadOnly);

this.inEditMode = (rowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0;

string value = null;

if (cell.Controls.Count > 0) {
Control control = cell.Controls[0];
if (control == null)
throw new InvalidOperationException(“The control cannot be extracted”);

if (inEditMode)
value = ((TextBox)control).Text;
value = ((LinkButton)control).Text;


if (dictionary.Contains(this.DataTextField))
dictionary[this.DataTextField] = value;
dictionary.Add(this.DataTextField, value);




Leave a Reply

Your email address will not be published. Required fields are marked *