Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Creating an ASP.NET GridView Custom Field of type DropDownList

4.19/5 (18 votes)
30 Nov 2008CPOL1 min read 103.2K   2.2K  
Sometimes you need to use a DropDownList in a GridView in a way to see the text of the field and save the value to the database. Here we extended the “BoundField” class, and add features to create a column type of “DropDownList”.

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.

Image 1

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:

GridEdit.jpg

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:

XML
<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:

SQL
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:

XML
<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:

C#
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:

C#
public override void ExtractValuesFromCell(IOrderedDictionary dictionary, 
       DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
    . . . .
    if (cell.Controls.Count > 0)
    {

        // Get column editor of type DropDownList of current cell 
        control = cell.Controls[0];
        DropDownList box = control as DropDownList;
        if ((box != null) && (includeReadOnly || box.Enabled))
        {
            obj2 = box.Text;
            if (obj2 != null)
            {

                // extract value from DropDownList
                ListItem itm = box.Items.FindByValue(obj2.ToString());
                obj3 = itm.Text;
            }

        }
    }
    if (obj2 != null)
    {
        if (dictionary.Contains(dataField))
        {
            dictionary[dataField] = obj2;
        }
        else
        {
            //put both text and value into the dictionary
            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.

C#
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))
    {
        // If data cell is in edit mode, create DropDownList editor for this cell
        // and set data properties.
        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 data cell is in edit mode, set selected value of DropDownList 
        if (dataValue != null)
        {

            ListItem itm = ((DropDownList)control).Items.FindByText(dataValue.ToString());
            ((DropDownList)control).Text = itm.Value;
        }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)