Introduction
Sometimes, you need to use a DropDownList
in a GridView
in a way to see the text of fields and save values in to your database. Here, we have extended the “BoundField
” class and added features to create a column type of “DropDownList
”.
For example, in this picture, you can see two tables, Customer and Category.
Suppose you need to edit the content of the Customer table with a GridView
and select “Customer Category” through a “DropDownList
”. You want to see the CategoryName
in the grid but save CategoryID
in to the database, like in this picture:
Background
You have two solutions:
- The first solution is to create a Template column of type
DropDownList
. - The second solution is to create a new column type with the “
DropDownList
” editor and introduce an “Entity Name” for it. Here, we have extended the “BoundField
” class and added features to create a column type of “DropDownList
”.
Using the code
Now, you can use this column type easily, like:
<CustomFields:ComboBoxField BusinessObjectName="CategoryBO"
DataTextField="CategoryName" DataValueField="CategoryID"
SelectMethod="GetCategories" DataField="Category"
IDDataField="CategoryID" SortExpression="Category"
HeaderText="Category"></CustomFields:ComboBoxField>
For this reason, you should join the main table with the referenced table and create a view containing both the text and the value of the combobox field:
CREATE VIEW vCustomers AS
SELECT dbo.Customers.CustomerID, dbo.Customers.FirstName, dbo.Customers.LastName,
dbo.Customers.CategoryID, dbo.Category.CategoryName AS Category FROM
dbo.Customers INNER JOIN
dbo.Category ON dbo.Customers.CategoryID = dbo.Category.CategoryID
And, create both text and value columns in the GridView
and set the value column “visiblity” to False
:
<CustomFields:ComboBoxField BusinessObjectName="CategoryBO"
DataTextField="CategoryName" DataValueField="CategoryID"
SelectMethod="GetCategories" DataField="Category"
IDDataField="CategoryID" SortExpression="Category"
HeaderText="Category"></CustomFields:ComboBoxField>
<asp:BoundField DataField="CategoryID"
HeaderText="CategoryID"
SortExpression="CategoryID"
Visible="False"/>
The first step is to create a new class inherited from the BoundField
class:
public class ComboBoxField:BoundField
{
. . .
The second step is to change the ExtractValuesFromCell
method to get the DropDownList
control for editing the cell in edit mode:
public override void ExtractValuesFromCell(IOrderedDictionary dictionary,
DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
. . . .
if (cell.Controls.Count > 0)
{
control = cell.Controls[0];
DropDownList box = control as DropDownList;
if ((box != null) && (includeReadOnly || box.Enabled))
{
obj2 = box.Text;
if (obj2 != null)
{
ListItem itm = box.Items.FindByValue(obj2.ToString());
obj3 = itm.Text;
}
}
}
if (obj2 != null)
{
if (dictionary.Contains(dataField))
{
dictionary[dataField] = obj2;
}
else
{
dictionary.Add(dataField, obj3);
dictionary.Add(this.IDDataField, obj2);
The third step is changing the InitializeDataCell
method to create the DropDownList
control in the editing cell.
protected override void InitializeDataCell(DataControlFieldCell cell,
DataControlRowState rowState)
{
Control child = null;
Control control2 = null;
if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) &&
!this.ReadOnly) || ((rowState & DataControlRowState.Insert)
!= DataControlRowState.Normal))
{
DropDownList box = new DropDownList();
box.DataSource =this.GetDataSource();
box.DataMember = this.BusinessObjectName;
box.DataTextField = this.DataTextField;
box.DataValueField = this.DataValueField;
box.DataBind();
.
.
.
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 (dataValue != null)
{
ListItem itm = ((DropDownList)control).Items.FindByText(dataValue.ToString());
((DropDownList)control).Text = itm.Value;
}