Click here to Skip to main content
Click here to Skip to main content

How to create custom bound fields in GridView

By , 30 Mar 2006
 

Introduction

This article describes about how to create your own custom column like asp:BoundField & asp:ButtonField and adding them dynamically to a grid view.

In one of my project I am being asked to develop code for a requirement

  • The number of columns is not known till the execution time. The columns can be of any number.
  • Some columns in the grid need to be editable.
  • Should be able to display controls like check box/list box in one of the column.

 

In this article I am going to describe about how to achieve the above said requirements by creating a custom column of my own and dynamic adding columns in the grid view. Here I have used the DataTable as the datasource. As data table provides more extendable features.

 

 Sample screenshot

Let’s walk through the steps.

  

Code walkthrough

 

Create a grid view in the page,

  1. Drag and drop the GridView control on to the page.

Or

  1. Manually type GridView control’s definition in the page.

 

<table border="0" cellpadding="0" cellspacing="0">

  <tr>

     <td><strong>How to create custom columns dynamically in a grid view</strong></td>

  </tr>

  <tr>

     <td>

       <asp:GridView ID="GrdDynamic" runat="server" AutoGenerateColumns="False" ShowHeader="true" ShowFooter="true">

       <Columns>

       </Columns>

       </asp:GridView>

     </td>

  </tr>

  <tr>

      <td>

        <asp:Button ID="cmdSave" runat="server" OnClick="cmdSave_Click" Text="Save" />

</td>

 </tr>

</table>

 

With this we are done with creating a GridView in the page.

Let’s move on to the code-beside to understand the background history of the page.

Here I will describe about, how to create our own custom bound field column.

 

//Iterate through the columns of the datatable to set the data bound field dynamically.

        foreach (DataColumn col in dt.Columns)

        {

            //Declare the bound field and allocate memory for the bound field.

            CustomBoundField bfield = new CustomBoundField();

 

            //Initalize the DataField value.

            bfield.DataField = col.ColumnName;

 

            //Initialize the HeaderText field value.

            bfield.HeaderText = col.ColumnName;

 

            //Check if any property has been defined for the editing.

            if (col.ExtendedProperties["Editable"] != null)

            {

                bfield.Editable = Convert.ToBoolean(col.ExtendedProperties["Editable"]);

            }

 

            //Check if any property has been defined for displaying the checkboxes.

            if (col.ExtendedProperties["CheckBox"] != null)

            {

                bfield.ShowCheckBox = Convert.ToBoolean(col.ExtendedProperties["CheckBox"]);

            }

 

            //Add the newly created bound field to the GridView.

            GrdDynamic.Columns.Add(bfield);

        }

   

Let’s start dissecting right from the top,

 

  1. Create a DataTable, which will hold the table definition and data for the Grid View. This table is used as a Data Source for the Grid View.
    DataTable dt = new DataTable();
  2. Once the Data Table is created, let’s add few columns to the Data Table.
  3. The logic behind creating dynamic column starts by creating a CustomBoundField instance.
  4. Once the CustomBoundField is created, I am initializing the DataField and HeaderText properties of the newly created CustomBoundField.We will come back to the CustomBoundField class in detail again.
  5. Once the creation of the dynamic column and assigning values to the column is complete. Add the column to the Grid View.

 

How to create the CustomBoundField

 

Till now the above-described method is the same old story as before, but the interesting part of this story starts when you look at the class CustomBoundField.

 

public class CustomBoundField : DataControlField

{

      public CustomBoundField()

      {

            //

            // TODO: Add constructor logic here

            //

      }

 

    #region Public Properties

 

    /// <summary>

    /// This property describe weather the column should be an editable column or non editable column.

    /// </summary>

    public bool Editable

    {

        get

        {

            object value = base.ViewState["Editable"];

            if (value != null)

            {

                return Convert.ToBoolean(value);

            }

            else

            {

                return true;

            }

        }

        set

        {

            base.ViewState["Editable"] = value;

            this.OnFieldChanged();

        }

    }

 

    /// <summary>

    /// This property is to describe weather to display a check box or not.

    /// This property works in association with Editable.

    /// </summary>

    public bool ShowCheckBox

    {

        get

        {

            object value = base.ViewState["ShowCheckBox"];

            if (value != null)

            {

                return Convert.ToBoolean(value);

            }

            else

            {

                return false;

            }

        }

        set

        {

            base.ViewState["ShowCheckBox"] = value;

            this.OnFieldChanged();

        }

    }

 

    /// <summary>

    /// This property describe column name, which acts as the primary data source for the column.

    /// The data that is displayed in the column will be retreived from the given column name.

    /// </summary>

    public string DataField

    {

        get

        {

            object value = base.ViewState["DataField"];

            if (value != null)

            {

                return value.ToString();

            }

            else

            {

                return string.Empty;

            }

        }

        set

        {

            base.ViewState["DataField"] = value;

            this.OnFieldChanged();

        }

    }

    #endregion

 

    #region Overriden Life Cycle Methods

    /// <summary>

    /// Overriding the CreateField method is mandatory if you derive from the DataControlField.

    /// </summary>

    /// <returns></returns>

    protected override DataControlField CreateField()

    {

        return new BoundField();

    }

 

    /// <summary>

    /// Adds text controls to a cell's controls collection. Base method of DataControlField is

    /// called to import much of the logic that deals with header and footer rendering.

    /// </summary>

    /// <param name="cell">A reference to the cell</param>

    /// <param name="cellType">The type of the cell</param>

    /// <param name="rowState">State of the row being rendered</param>

    /// <param name="rowIndex">Index of the row being rendered</param>

    public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)

    {

        //Call the base method.

        base.InitializeCell(cell, cellType, rowState, rowIndex);

 

        switch (cellType)

        {

            case DataControlCellType.DataCell:

                this.InitializeDataCell(cell, rowState);

                break;

            case DataControlCellType.Footer:

                this.InitializeFooterCell(cell, rowState);

                break;

            case DataControlCellType.Header:

                this.InitializeHeaderCell(cell, rowState);

                break;

        }

    }

    #endregion

 

    #region Custom Protected Methods

    /// <summary>

    /// Determines which control to bind to data. In this a hyperlink control is bound regardless

    /// of the row state. The hyperlink control is then attached to a DataBinding event handler

    /// to actually retrieve and display data.

    ///

    /// Note: This control was built with the assumption that it will not be used in a gridview

    /// control that uses inline editing. If you are building a custom data control field and

    /// using this code for reference purposes key in mind that if your control needs to support

    /// inline editing you must determine which control to bind to data based on the row state.

    /// </summary>

    /// <param name="cell">A reference to the cell</param>

    /// <param name="rowState">State of the row being rendered</param>

    protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)

    {

        //Check to see if the column is a editable and does not show the checkboxes.

        if (Editable & !ShowCheckBox)

        {

            string ID = Guid.NewGuid().ToString();

            TextBox txtBox = new TextBox();

            txtBox.Columns = 5;

            txtBox.ID = ID;

            txtBox.DataBinding += new EventHandler(txtBox_DataBinding);

 

            cell.Controls.Add(txtBox);

        }

        else

        {

            if (ShowCheckBox)

            {

                CheckBox chkBox = new CheckBox();

                cell.Controls.Add(chkBox);

            }

            else

            {

                Label lblText = new Label();

                lblText.DataBinding += new EventHandler(lblText_DataBinding);

                cell.Controls.Add(lblText);

            }

        }

    }

 

    void lblText_DataBinding(object sender, EventArgs e)

    {

        // get a reference to the control that raised the event

        Label target = (Label)sender;

        Control container = target.NamingContainer;

 

        // get a reference to the row object

        object dataItem = DataBinder.GetDataItem(container);

 

        // get the row's value for the named data field only use Eval when it is neccessary

        // to access child object values, otherwise use GetPropertyValue. GetPropertyValue

        // is faster because it does not use reflection

        object dataFieldValue = null;

 

        if (this.DataField.Contains("."))

        {

            dataFieldValue = DataBinder.Eval(dataItem, this.DataField);

        }

        else

        {

            dataFieldValue = DataBinder.GetPropertyValue(dataItem, this.DataField);

        }

 

        // set the table cell's text. check for null values to prevent ToString errors

        if (dataFieldValue != null)

        {

            target.Text = dataFieldValue.ToString();

        }

    }

 

    protected void InitializeFooterCell(DataControlFieldCell cell, DataControlRowState rowState)

    {

        CheckBox chkBox = new CheckBox();

        cell.Controls.Add(chkBox);

    }

 

    protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState)

    {

        Label lbl = new Label();

        lbl.Text = this.DataField;

        cell.Controls.Add(lbl);

    }

 

    void txtBox_DataBinding(object sender, EventArgs e)

    {

        // get a reference to the control that raised the event

        TextBox target = (TextBox)sender;

        Control container = target.NamingContainer;

 

        // get a reference to the row object

        object dataItem = DataBinder.GetDataItem(container);

 

        // get the row's value for the named data field only use Eval when it is neccessary

        // to access child object values, otherwise use GetPropertyValue. GetPropertyValue

        // is faster because it does not use reflection

        object dataFieldValue = null;

 

        if (this.DataField.Contains("."))

        {

            dataFieldValue = DataBinder.Eval(dataItem, this.DataField);

        }

        else

        {

            dataFieldValue = DataBinder.GetPropertyValue(dataItem, this.DataField);

        }

 

        // set the table cell's text. check for null values to prevent ToString errors

        if (dataFieldValue != null)

        {

            target.Text = dataFieldValue.ToString();

        }

    }

    #endregion

}

 

Any class that should be used as a custom bound field column should be inherited from the DataControlField class.

DataControlField serves as the base class for all data control field types, which represent a column of data in tabular data-bound controls such as Details View and Grid View.

 

In the newly created class, I have created properties

  1. Editable
  2. ShowCheckBox
  3. DataField

 

Editable

This property describe weather the column should be an editable column or non editable column.

 

ShowCheckBox

This property is to describe weather to display a check box or not.

 

DataField

This property describe column name, which acts as the primary data source for the column. The data that is displayed in the column will be retreived from the given column name.

 

Now, we have to override one important property i.e. InitializeCell to create the required format for the column.

 

InitializeCell:

Types derived from DataControlField implement the InitializeCell method to add text and controls to a DataControlFieldCell object that belongs to a data control that uses tables to display a user interface (UI). These data controls create the complete table structure row by row when their respective CreateChildControls methods are called.

The InitializeCell method is called by the InitializeRow method of data controls such as DetailsView and GridView.

 

In this article, lets have a look at the initializeCell method’s definition

 

switch (cellType)

{

   case DataControlCellType.DataCell:

this.InitializeDataCell(cell, rowState);

      break;

   case DataControlCellType.Footer:

      this.InitializeFooterCell(cell, rowState);

      break;

   case DataControlCellType.Header:

      this.InitializeHeaderCell(cell, rowState);

      break;

}

 

Based on the passed cell type, invoking the corresponding methods to initialize the cells data accordingly. This method would be called for every row that is created in the Grid View.

 

InitializeFooterCell:

InitializeFooterCell is a private method, which will be called while creating the footer row in the Grid View. To see how the footer row looks like, make sure you have the property ShowFooter="true". Then only the footer row can be seen. The code displays the checkboxes in the footer row.

 

InitializeHeaderCell:

InitializeHeaderCell is a private method, which will be called while creating the header row in the Grid View. To see how the header row looks like make sure you have the property ShowHeader="true". While creating the header or footer you can create more controls than what I have shown in the example like hiddencontrols, table control etc.

 

InitializeDataCell:

InitializeDataCell is a private method, where most of the magic will be done. In this method at first, I am checking to see if the column is an editable and does not show the checkboxes. If the condition is met, I am creating a text box control and adding the control to the table’s cell, otherwise I am checking weather I have to show the checkbox or label control. If you notice one of the interesting funda is the DataBinding event of the text box or label control. The DataBinding event occurs when the server control binds to a data source. Since I am overriding the default behaviour of the system. I have to manually set the value for the text box also.  Have a look at the attached code for more details on how to read the data from the container and set the values in to the text box.

 

The various advantages with this approach are

  • Customize the appearance of the control.
  • Format how the UI should look like. Can format the header, footer and item
  • Can add JavaScript support like the way we support from the code beside.

 

That’s your entire dynamic GridView is ready. I hope this information would be helpful.

Enjoy programming.

PAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">

 

InitializeHeaderCell:

InitializeHeaderCell is a private method, which will be called while creating the header row in the Grid View. To see how the header row looks like make sure you have the property ShowHeader="true". While creating the header or footer you can create more controls than what I have shown in the example like hiddencontrols, table control etc.

 

InitializeDataCell:

InitializeDataCell is a private method, where most of the magic will be done. In this method at first, I am checking to see if the column is an editable and does not show the checkboxes. If the condition is met, I am creating a text box control and adding the control to the table’s cell, otherwise I am checking weather I have to show the checkbox or label control. If you notice one of the interesting funda is the DataBinding event of the text box or label control. The DataBinding event occurs when the server control binds to a data source. Since I am overriding the default behaviour of the system. I have to manually set the value for the text box also.  Have a look at the attached code for more details on how to read the data from the container and set the values in to the text box.

 

The various advantages with this approach are

  • Customize the appearance of the control.
  • Format how the UI should look like. Can format the header, footer and item
  • Can add JavaScript support like the way we support from the code beside.

 

That’s your entire dynamic GridView is ready. I hope this information would be helpful.

Enjoy programming.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Devakumar Sai Chinthala
Founder Articledean.com & conveygreetings.com
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionAccess in MarkUpmemberGirish Chawrai2 Nov '11 - 23:52 
Hi,
You have added the newly created field to the GridView from the code behind. When I tried to add the same from MarkUp, I couldn't. Are there any settings to be made for achieving this?
Thanks,
Girish Chawrai.

GeneralMy vote of 1memberMlsoun10 Jun '11 - 0:22 
design Frown | :-(
GeneralDon't Add ID to the textboxesmemberahmad.itplanet22 Mar '11 - 2:35 
In order to be able to get the text value of the text boxes, I had to remove the part of code defining the ID to the added textbox using GUID
 
if (Editable & !ShowCheckBox)
            {
                //string ID = Guid.NewGuid().ToString();
                TextBox txtBox = new TextBox();
                txtBox.Columns = 5;
                //txtBox.ID = ID;
                txtBox.DataBinding += new EventHandler(txtBox_DataBinding);
                cell.Controls.Add(txtBox);
            }

GeneralMy vote of 1membersaleem45824 Jan '11 - 23:29 
nothing
GeneralMy vote of 5memberavishekrc11 Oct '10 - 0:54 
It really helped me!
GeneralMy vote of 2membervasuhajare10 Aug '10 - 23:46 
good
GeneralCheckBoxes are all uncheckedmembergerth12319 Jul '10 - 4:26 
I tried to use this example for 1 textcolumn and 3 more CheckBox-Columns in each row. I create a DataTable dt, add 4 columns and add several Rows like this
 
...
dt.rows.Add("text", true, false, true);
dt.rows.Add("text", false, true, true);
...
 
Then I use dt as DataSource for the Gridview and bind data. But all Checkboxes are unchecked, no matter which values of true/false were in the DataTable.
 
Strange thing:
If I set the ExtendedProperties["CheckBox"] to false, it shows column 2-4 in a textbox BUT THEN there are the correct values of TRUE and FALSE in it. So the problem is due to the CheckBox representation. I am thankful for any hint!
GeneralIn order to set the Header Text have to change the code.memberFir Last Name17 Jan '09 - 8:02 
protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState)
{
Label lbl = new Label();
lbl.Text = this.DataField;
cell.Controls.Add(lbl);
}
 

//Should be:
 
protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState)
{
Label lbl = new Label();
lbl.Text = this.HeaderText;
cell.Controls.Add(lbl);
}
GeneralChange specific cell property to calender cellmembersashdude4 Oct '08 - 14:41 
Hi
 
Using grid table how can I change the properties of a specific cell to a calender cell
GeneralUnable to get values from TextBox, CheckBox as Item Template of Grid ViewmemberMember 371362314 Aug '08 - 6:27 
Hello,
 
I am unable to get values from Grid View Item Templates like (TextBox and CheckBox) Values. Here is my code to create TextBox Item Template:
 

public class TextBoxItem : ITemplate
{
 

private string _strName="";
 

public TextBoxItem(bool editable , string name)
{
readOnly = (editable == true) ? false : true;
_strName = name;
 
}
 
void ITemplate.InstantiateIn(Control container)
{
TextBox box = new TextBox();
box.ID = _strName;

container.Controls.Add(box);
}
 
}
 
private bool readOnly = true;
}
}
 

 

and Here is the code of Grid where I have added this template to Grid View:
 
TemplateField tcTextBox = new TemplateField();
tcTextBox.ItemTemplate = new TextBoxItem(true,"TextBox1");
tcTextBox.HeaderText = "Release Quantity";
_dgViewMaterial.Columns.Add(tcTextBox);
 

 
And here is the code in Button click where I am trying to get values from textbox:
 
foreach (GridViewRow r in _dgViewMaterial.Rows)
{
TextBox cb = (TextBox)_r.FindControl("TextBox1");
if (cb != null) _sMex += "TextBox 1 Found:" + cb.Text;
else _sMex += " TextBox 1 Not Found:";
 
}
 

It always return me with saying TextBox 1 not found..
 
Please let me know
GeneralMaintaining viewstatememberKennon20017 Nov '07 - 22:52 
I used your custom bound fields and find it really good and easy to add extended functions. However, I don't know how to maintain the viewstate of the textbox. For example, I added a "Add Row" button to add new row to the gridview when it is clicked. All textboxs of the existing rows are blank after adding the new row. How can I fix it?
Thank you very much!
 
Kennon

QuestionAccessing the controls in GridView.memberPatilSuhas23 Oct '07 - 20:27 
Hi,
 
I am Suhas.
 
I have created a gridview using custom bound fields as mentioned in this article. While creating each CustomBoundField, I have given new GUID for each control inside InitialiseDataCell function. Now I want to access each control for reading values inside it. For accessing control in the columns we need to use "FindControl" property of column which requires control id to find it. But how can I get the control id which is generated at runtime?
 
Pleas, first let me   know if I am going in right direction to access the control's value. If yes please help me to find out the control id at runtime.
 
I used cell's ClientId,UniqueId and ID   property. But it is returning null.
 

 
Thanks & Regards
Suhas.
QuestionHow to access a dropdown list in a grid view from codebehindmemberVimal Joseph6 Jul '07 - 5:14 
Hello ,
How can i access a dropdown list inside a grid view from codebehind.
I placed a dropdown list inside gridview. But am not able access it from code behind for populating data.
 
Please help me,
 

 
Vimal Joseph
Software Engineer
Quest Informatics

AnswerRe: How to access a dropdown list in a grid view from codebehindmemberAitorku12 Feb '10 - 1:33 
If someone knows how to do it, please write the code. It´s helpful for people in the future, in my case I am having the same problem
GeneralSortingmembervasigus12 May '07 - 10:44 
Hello SaidevKumar,
 
Would you be able to point me in the right direction with regards to sorting a grid that implements your customboundfield??? I have tried to do this but am unable to get the header text to show links and do proper postbacks for sort action.
 
Thanks,
Gust..
QuestionGetting data for textboxmemberRitesh_Gadodia17 Apr '07 - 20:55 
hi,
i am facing problem in geting data after button clicked , the textbox return null value in gridview . plaese answer this question as elary as possilbe.
Thanks
Thanks And regrads
Ritesh S. Gadodia
Sniff | :^)
AnswerRe: Getting data for textboxmembermotseu18 Jun '07 - 2:04 
remove the id from textbox
 
//txtBox.ID = ID;
QuestionCheckboxmember-u-29 Nov '06 - 13:31 
I have tried the codes and its working fine, but when clicking the save button it produce an error. And i want to what is the code for it to retrieve data on specific rows where a tick is present in the checkbox and past the value into database.
QuestionHow to create drop down list bound fields in GridView Edit Modememberdvd3n15 Oct '06 - 22:35 
Hi, all
 
Please help me, how to create drop down list bound fields in GridView Edit Mode
 
thanks

 
David
AnswerRe: How to create drop down list bound fields in GridView Edit Modememberdodiggitydag24 Oct '06 - 10:28 
The code in the next post is based on
 
http://www.metabuilders.com/Tools/BoundLookupColumn.aspx
 
BoundLookupColumn is for the DataGrid, so slightly different and it is just as picky, although I think generic collections work.   I have been using it for a while now so many of the bugs are fixed.
 
An example page would look like:
 
<asp:GridView ID="grid" runat="server" />
      <Columns>
            <Utilities:BoundLookupField DataField="User_Name" HeaderText="User Name"
                  LookUpDataTextField="User_Name" LookUpDataValueField="PK_Users_ID" />
            <asp:BoundField DataField="Description" HeaderText="Description"
                  SortExpression="Description" />
            <asp:BoundField DataField="Time" HeaderText="Time" SortExpression="Time" />
      </Columns>
</asp:GridView>
 
Then the easiest way to bind is in the code-behind:
 
// Set the look up data source
BoundLookupField blc = (BoundLookupField) gv.Columns[0];
blc.LookupDataSource = dtUsers;
 
// Bind the data grid
gv.DataSource = dtTracking;
gv.DataBind();
 
-- DC
AnswerRe: How to create drop down list bound fields in GridView Edit Modememberdodiggitydag24 Oct '06 - 10:30 
Please see previous post also...
 

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace Utilities.WebControls
{
      /// <summary>
      /// A column type for the <see cref="GridView"/> control that is bound to a
      /// field in a data source and restricts the values to records from another
      /// source.
      /// </summary>
      /// <remarks><para>Use the <see cref="BoundLookupField"/> column type in a
      /// <see cref="GridView"/> control to display the contents of a field in the
      /// data source in a single column. The field is linked to the
      /// BoundLookupField, so any updates in the data source are reflected in the
      /// corresponding cells of the GridView control.</para>
      /// <para>The <see cref="LookupDataSource"/> should have unique values in
      /// the <see cref="LookupDataTextField"/> column or unexpected results could
      /// occur.</para>
      /// <para>The values for the LookupDataTextField of the LookupDataSource
      /// should match the values in the DataField column of the DataSource.</para></remarks>
      [System.Runtime.InteropServices.ComVisible(false)]
      public sealed class BoundLookupField : BoundField
      {
            #region Private
 
            private PropertyDescriptor boundFieldDesc;
            private bool boundFieldDescValid;
            private object lookupDataSource;
            private string lookupDataMember;
            private Style _nullStyle;
            private bool _scriptRegistered;
            private string _uniqueID;
 
            #endregion
 
            #region ctor
 
            /// <summary>
            /// Creates a new instance of the <see cref="BoundLookupField"/>
            /// control.
            /// </summary>
            public BoundLookupField() : base() {}
 
            #endregion
 
            #region Methods
 
            /// <summary>
            /// Handles binding the data to the table cell.
            /// </summary>
            /// <param name="sender">The <see cref="TableCell"/>.</param>
            /// <param name="e"></param>
            private void CellDataBinding(object sender, EventArgs e)
            {
                  TableCell cell = (TableCell) sender;
                  object dataItem = ((GridViewRow) cell.NamingContainer).DataItem;
 
                  // Ensure that the bound field exists in the datasource.
                  if (!this.boundFieldDescValid)
                  {
                        if (this.DataField != "!")
                        {
                              this.boundFieldDesc = System.ComponentModel.TypeDescriptor.GetProperties(dataItem).Find(this.DataField, true);
 
                              if (this.boundFieldDesc == null && !this.DesignMode)
                                    throw new HttpException("Field Not Found: " + this.DataField);
                        }
                        this.boundFieldDescValid = true;
                  }
 
                  // Get the underlying value
                  String underlyingValue = this.GetUnderlyingValue(ref dataItem);
 
                  // Set the text of the cell to the display value for the field.
                  if (string.IsNullOrEmpty(underlyingValue))
                        cell.Text = "&nbsp;";
                  else if (underlyingValue == null)
                        cell.Text = this.NullDisplayText;
                  else
                        cell.Text = underlyingValue;
            }
 
            /// <summary>
            /// Initializes a cell in the <see cref="GridView"/>.
            /// </summary>
            /// <param name="cell">The field cell.</param>
            /// <param name="cellType">The type of cell.</param>
            /// <param name="rowState">The row state.</param>
            /// <param name="rowIndex">The row index.</param>
            public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
            {
                  if (cell == null)
                        throw new ArgumentNullException("cell");
 
                  // Header / footer?
                  if (cellType != DataControlCellType.DataCell)
                  {
                        // Call the base method.
                        base.InitializeCell(cell, cellType, rowState, rowIndex);
                        return;
                  }
 
                  // Determine the databinding container and create the ddl if
                  // neccessary.
                  if (!this.ReadOnly && (this.AlwaysRenderEditMode ||
                        (rowState & DataControlRowState.Edit) == DataControlRowState.Edit))
                  {
                        cell.Controls.Clear();
 
                        DropDownList ddl = new DropDownList();
 
                        if (this.DesignMode)
                              ddl.Items.Add("Databound");
                        else if (this.DataField.Length != 0)
                        {
                              ddl.DataSource = this.LookupDataSource;
                              ddl.DataTextField = this.LookupDataTextField;
                              ddl.DataTextFormatString = this.LookupDataFormatString;
                              ddl.DataMember = this.LookupDataMember;
                              ddl.DataValueField = this.LookupDataValueField;
                              ddl.DataBound += new EventHandler(ListDataBound);
                        }
 
                        cell.Controls.Add(ddl);
                  }
                  else if (cellType == DataControlCellType.DataCell && this.DataField.Length != 0)
                  {
                        if (this.DesignMode)
                              cell.Text = "Databound";
                        else
                              cell.DataBinding += new EventHandler(CellDataBinding);
                  }
                  else
                        // Call the base method.
                        base.InitializeCell(cell, cellType, rowState, rowIndex);
            }
 
            /// <summary>
            /// Finds the correct item in the list from the DataItem's value.
            /// </summary>
            /// <param name="dataItem">The data item.</param>
            /// <returns>The underlying string value.</returns>
            private string GetUnderlyingValue(ref object dataItem)
            {
                  object dataItemDescriptorValue = dataItem;
 
                  if (this.boundFieldDesc != null)
                        dataItemDescriptorValue = this.boundFieldDesc.GetValue(dataItem);
 
                  if (dataItemDescriptorValue == null)
                        return string.Empty;
                  else
                        return base.FormatDataValue(dataItemDescriptorValue, false);
            }
 
            /// <summary>
            /// Sets the selected item on the drop down list for edit items.
            /// </summary>
            /// <param name="sender">The <see cref="DropDownList"/>.</param>
            /// <param name="e">The <see cref="EventArgs"/>.</param>
            private void ListDataBound(object sender, EventArgs e)
            {
                  DropDownList ddl = (DropDownList) sender;
                  object dataItem = ((GridViewRow) ddl.NamingContainer).DataItem;
                  string dataFieldValue;
 
                  // Get the value of the item from the GridView
                  if (this.LookupDataFormatString.Length != 0)
                        dataFieldValue = DataBinder.Eval(dataItem, this.DataField).ToString();
                  else
                        dataFieldValue = DataBinder.Eval(dataItem, this.DataField, this.LookupDataFormatString);
 
                  // Format the value if requested
                  if (this.LookupDataFormatString.Length != 0)
                        dataFieldValue = String.Format(this.LookupDataFormatString, dataFieldValue);
 
                  // Add a null item if allowed
                  if (this.AllowNulls)
                        ddl.Items.Insert(0, new ListItem(this.NullDisplayText, string.Empty));
 
                  // Find the item to select
                  ListItem currentItem = ddl.Items.FindByText(dataFieldValue);
 
                  // Select the correct item
                  if (currentItem != null)
                        ddl.SelectedIndex = ddl.Items.IndexOf(currentItem);
                  else if (this.AllowNulls)
                        ddl.SelectedIndex = 0;
            }
 
            #endregion
      }
}
 

DANG - ok, properties are in the next post...
AnswerRe: How to create drop down list bound fields in GridView Edit Modememberdodiggitydag24 Oct '06 - 10:31 
ok this is the last post hopefully.   paste this code inside of the class in the previous post:
 

            #region Properties
 
            /// <summary>
            /// Gets or sets if the values always be shown in text boxes.
            /// </summary>
            [Description("Should the values always be shown in drop down lists?"), DefaultValue(false), Category("Behavior")]
            public bool AlwaysRenderEditMode
            {
                  get
                  {
                        object savedData = this.ViewState["AlwaysRenderEditMode"];
 
                        if (savedData != null)
                              return (bool) savedData;
                        else
                              return false;
                  }
                  set
                  {
                        this.ViewState["AlwaysRenderEditMode"] = value;
 
                        this.OnFieldChanged();
                  }
            }
 
            /// <summary>
            /// Gets or sets a value that indicates whether the items in the
            /// BoundColumn includes a null choice.
            /// </summary>
            /// <remarks>When set to true, a ListItem with <see
            /// cref="String.Empty"/> as the value will be added as the first choice
            /// in the list. The display value of the ListItem is set with
            /// NullDisplayValue, which defaults to <see cref="String.Empty"/>. If
            /// you require a more custom handling of nulls, set AllowNulls to
            /// false, and modify the LookupDataSource prior to DataBinding the
            /// grid.</remarks>
            [Description("Gets or sets a value that indicates whether the items in the drop down list includes a null choice."),
            DefaultValue(false), Category("Behavior")]
            public bool AllowNulls
            {
                  get
                  {
                        object cachedValue = this.ViewState["AllowNulls"];
 
                        if (cachedValue != null)
                              return (bool) cachedValue;
 
                        return false;
                  }
                  set
                  {
                        this.ViewState["AllowNulls"] = value;
                        this.OnFieldChanged();
                  }
            }
 
            /// <summary>
            /// The data source for the selection list when the cell is in edit
            /// mode.
            /// </summary>
            [Description("The data source for the selection list when the cell is in edit mode."),
            DefaultValue(null), Bindable(true), Category("Data")]
            public object LookupDataSource
            {
                  get
                  {
                        return lookupDataSource;
                  }
                  set
                  {
                        if (value as IListSource != null || value as IEnumerable != null)
                              this.lookupDataSource = value;
                        else
                              throw new ArgumentException("Invalid data source type for the LookupDataSource.");
                  }
            }
 
            /// <summary>
            /// The data source member for the selection list when the cell is in
            /// edit mode.
            /// </summary>
            [Description("The data source member for the selection list when the cell is in edit mode."),
            DefaultValue(""), Category("Data")]
            public string LookupDataMember
            {
                  get
                  {
                        return lookupDataMember;
                  }
                  set
                  {
                        lookupDataMember = value;
                  }
            }
 
            /// <summary>
            /// The field of the data source to be used as the value for the
            /// selection list when the cell is in edit mode.
            /// </summary>
            [Description("The field of the data source to be used as the value for the selection list when the cell is in edit mode."),
            DefaultValue(""), Category("Data")]
            public string LookupDataValueField
            {
                  get
                  {
                        object savedState = this.ViewState["LookupDataValueField"];
                        if (savedState != null)
                              return (string) savedState;
 
                        return String.Empty;
                  }
                  set
                  {
                        this.ViewState["LookupDataValueField"] = value;
                        this.OnFieldChanged();
                  }
            }
 
            /// <summary>
            /// The field of the data source to be used as the visible text for the
            /// selection list when the cell is in edit mode.
            /// </summary>
            [Description("The field of the data source to be used as the visible text for the selection list when the cell is in edit mode."),
            DefaultValue(""), Category("Data")]
            public string LookupDataTextField
            {
                  get
                  {
                        object savedState = this.ViewState["LookupDataTextField"];
 
                        if (savedState != null)
                              return (string) savedState;
 
                        return String.Empty;
                  }
                  set
                  {
                        this.ViewState["LookupDataTextField"] = value;
                        this.OnFieldChanged();
                  }
            }
 
            /// <summary>
            /// Gets or sets the string that specifies the display format for items
            /// in the column.
            /// </summary>
            [Description("Gets or sets the string that specifies the display format for items in the column."),
            DefaultValue(""), Category("Data")]
            public string LookupDataFormatString
            {
                  get
                  {
                        object savedState = this.ViewState["LookupDataFormatString"];
 
                        if (savedState != null)
                              return (string) savedState;
 
                        return String.Empty;
                  }
                  set
                  {
                        this.ViewState["LookupDataFormatString"] = value;
                        this.OnFieldChanged();
                  }
            }
 
            #endregion
GeneralPage failure at design timememberKirk Quinbar21 Jun '06 - 4:53 
I created a custom bound field as described and it works perfect at runtime. The problem is that when I am in .NET and go from the html view of my page to the design view of my page, I don't get the nice gridview editor. It just generates a smaller gray box where the grid should be and says that my field that I set in the DataField property does not exist or gives me an index out of range error. If I take out the code in the Databinding subroutine, then the design mode works fine. I am not setting my sqldatasource until runtime, so .NET must be generating its down sample dataset which obviously would not have my fields.
 
any ideas on how the change the databinding subroutine to make it work fine at design time?
 
Kirk Quinbar
Zywave, Inc.
GeneralFixed it!memberKirk Quinbar21 Jun '06 - 5:08 
woops, I should have just tried this before I posted, but if anyone else wants to know how to prevent the error. You will have to excuse the VB code. I converted this to vb since that is what we use.
 
'class level variable
Private mbDesignMode As Boolean = HttpContext.Current Is Nothing
 
'within databinding code, surround the databinding code with a check for designmode
If Not mbDesignMode Then
If DataField.Contains(".") Then
dataFieldValue = DataBinder.Eval(dataItem, DataField)
Else
dataFieldValue = DataBinder.GetPropertyValue(dataItem, DataField)
End If
End If

 
Kirk Quinbar
Zywave, Inc.
QuestionWondering why creating GridView Fails in code?memberpkellner18 May '06 - 8:36 
When I make a modification to your code by making the GridView in code
 
Gridview GrdDynamic = new GridView();
 
The cells don't get loaded with data. Is the runat="server" doing something special I can do in code?
 
Or is it something else I'm not understanding.
 
Thanks, -Peter
 

http://peterkellner.net

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 31 Mar 2006
Article Copyright 2006 by Devakumar Sai Chinthala
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid