I managed to override the Boundfield to display a dropdownlist if I put it in a Gridview.
protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
Control child = null;
Control cellControl = null;
if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) && !this.ReadOnly)
|| ((rowState & DataControlRowState.Insert) != DataControlRowState.Normal))
{
// If data cell is in edit mode, create DropDownList editor for this cell
// and set data properties.
DropDownList box = new DropDownList();
box.Items.Add(DefaultValueText);
box.DataSource = this.GetDataSource();
box.DataMember = this.BusinessObjectName;
box.DataTextField = this.DataTextField;
box.DataValueField = this.DataValueField;
box.AppendDataBoundItems = true;
box.ToolTip = this.HeaderText;
cell.Controls.Add(box);
box.DataBind();
// if in edit mode, prepare dropdown for binding
if ((this.DataField.Length != 0) && ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal))
{
cellControl = box;
}
}
else if (this.DataField.Length != 0) // if in read only mode, prepare cell for binding
{
cellControl = cell;
}
if ((cellControl != null) && base.Visible)
{
cellControl.DataBinding += new EventHandler(this.OnDataBindField);
}
}
protected override void OnDataBindField(object sender, EventArgs e)
{
Control control = (Control)sender;
Control namingContainer = control.NamingContainer;
object dataValue = this.GetValue(namingContainer);
bool encode = (this.SupportsHtmlEncode && this.HtmlEncode) && (control is TableCell);
string str = this.FormatDataValue(dataValue, encode);
if (control is TableCell)
{
if (str.Length == 0)
{
str = " ";
}
((TableCell)control).Text = str;
}
else
{
//If data cell is in edit mode, set selected value of DropDownList
if (dataValue != null)
{
DropDownList dropDownList = (DropDownList) control;
ListItem itm = dropDownList.Items.FindByText(dataValue.ToString());
if (itm != null)
{
dropDownList.Text = itm.Value;
}
else
((DropDownList)control).Text = DefaultValueText;
}
}
}
The last feature I added is a default value/ additional item to display if nothing has been selected, like "please select" for example. I can set this through the property DefaultValueText in the OnDataBind event.
Now here's the problem I am facing:
In InitializeDataCell, if I set
box.AppendDataBoundItems = true;
and call
box.DataBind();
The dropdownlist has all the items plus the additional default item. It also works nicely in the OnDataBind event, where I can now select the default if the databound item does not contain a value.
But when the dropdownlist is displayed in the gridview, it contains the default value plus everything from the datasource TWICE, because I set AppendDataBoundItems = true, which leads the dropdown to NOT clear it's items when items are added The gridview must be calling databind twice, but it's only registering once in the OnDataBind event method. I only see one call there, and in that moment, everything is fine, the dropdown contains the default item plus one of each item from the datasource.
Any suggestions where or how I can handle the databinding so that I have full control over the databinding?