views:

1760

answers:

3

Is it possible to do the following in a DataGridView:

In the same column I want to change the control type of each row between DataGridViewTextBoxColumn and DataGridViewComboBoxColumn?

(this is because sometimes I want to display a drop down list and other times I just want the user to enter a freehand value).

Thanks,

P.S. I am using C#

A: 

You could create a template column with both controls in, hide the one you don't want, and bind the other to the datasource in code.

orthod0ks
Template columns are for ASP.NET GridView, not WinForms DataGridView...
Thomas Levesque
Ahh, my bad. It's been a while since I worked with WinForms.
orthod0ks
+1  A: 

You could create your own class inherited from DataGridViewCell, and override the adequate virtual members (InitializeEditingControls, EditType, maybe a few others). You can then create a DataGridViewColumn with an instance of this class as the cell template

Thomas Levesque
Thanks for this. Looks like the right track. Unfortunately I am newish to this and I cannot get the cells to appear no matter what I do. I have overriden EditType as suggested. If I inherit from say 'DataGridViewTextBoxCell' then i can see the cell, inheriting from 'DataGridViewCell' and overriding EditType to return typeof(DataGridViewTextBoxEditingControl) gives me a blank cell - I can see the column though. I am sure there is something obvious I have missed.
MT
It just seems that the view mode control is not showing or has a width if zero? I can tab to the control, hit F2 and type a value. When I exit I can't see it, when I return to edit mode it is still there.
MT
I think you also need to override PositionEditingPanel and PositionEditingControl. But I never did it myself, so I can only guess... You should use Reflector to have a look at the code for standard DataGridViewCells, it will probably show you what you need to do
Thomas Levesque
A: 

I've recently had a similar usecase, and ended up writing something like the below code:

Write a custom Cell and Column class, and override the EditType and InitializeEditingControl methods on the cell, to return different controls as appropriate (here I'm just databinding to a list of a custom class with .useCombo field indicating what control to use):

// Define a column that will create an appropriate type of edit control as needed.
public class OptionalDropdownColumn : DataGridViewColumn
{
    public OptionalDropdownColumn()
        : base(new PropertyCell())
    {
    }

    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }
        set
        {
            // Ensure that the cell used for the template is a PropertyCell.
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(PropertyCell)))
            {
                throw new InvalidCastException("Must be a PropertyCell");
            }
            base.CellTemplate = value;
        }
    }
}

// And the corresponding Cell type
public class OptionalDropdownCell : DataGridViewTextBoxCell
{

    public OptionalDropdownCell()
        : base()
    {           
    }

    public override void InitializeEditingControl(int rowIndex, object
        initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // Set the value of the editing control to the current cell value.
        base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);

        DataItem dataItem = (DataItem) this.OwningRow.DataBoundItem;
        if (dataItem.useCombo)
        {
            DataGridViewComboBoxEditingControl ctl = (DataGridViewComboBoxEditingControl)DataGridView.EditingControl;
            ctl.DataSource = dataItem.allowedItems;
            ctl.DropDownStyle = ComboBoxStyle.DropDownList;
        }
        else
        {
            DataGridViewTextBoxEditingControl ctl = (DataGridViewTextBoxEditingControl)DataGridView.EditingControl;
            ctl.Text = this.Value.ToString();
        }
    }

    public override Type EditType
    {
        get
        {
            DataItem dataItem = (DataItem)this.OwningRow.DataBoundItem;
            if (dataItem.useCombo)
            {
                return typeof(DataGridViewComboBoxEditingControl);
            }
            else
            {
                return typeof(DataGridViewTextBoxEditingControl);
            }
        }
    }
}

Then just add a column to your DataGridView of this type, and the correct edit control should be used.

Brian