Adding Different DataGridView Cell Types to a Column

34,134

Solution 1

Have you looked at these:

Mixing cell types in a DataGridViewColumn

DataGridview cells of one column can't have different type

http://social.msdn.microsoft.com/Forums/windows/en-US/148b232b-ce8c-4c49-b35d-50d8a5c448d1/different-cell-types-in-a-datagridview-column

Following from the MSDN article...

There are two ways to do this:

  1. Cast a DataGridViewCell to a certain cell type that exists. For example, convert a DataGridViewTextBoxCell to DataGridViewComboBoxCell type.
  2. Create a control and add it into the controls collection of DataGridView, set its location and size to fit the cell that to be host.

Here's some sample code which illustrates these tricks:

private void Form5_Load(object sender, EventArgs e)
{
    DataTable dt = new DataTable();
    dt.Columns.Add("name");
    for (int j = 0; j < 10; j++)
    {
        dt.Rows.Add("");
    }
    this.dataGridView1.DataSource = dt;
    this.dataGridView1.Columns[0].Width = 200;

    /*
     * First method : Convert to an existed cell type such ComboBox cell,etc
     */

    DataGridViewComboBoxCell ComboBoxCell = new DataGridViewComboBoxCell();
    ComboBoxCell.Items.AddRange(new string[] { "aaa","bbb","ccc" });
    this.dataGridView1[0, 0] = ComboBoxCell;
    this.dataGridView1[0, 0].Value = "bbb";

    DataGridViewTextBoxCell TextBoxCell = new DataGridViewTextBoxCell();
    this.dataGridView1[0, 1] = TextBoxCell;
    this.dataGridView1[0, 1].Value = "some text";

    DataGridViewCheckBoxCell CheckBoxCell = new DataGridViewCheckBoxCell();
    CheckBoxCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
    this.dataGridView1[0, 2] = CheckBoxCell;
    this.dataGridView1[0, 2].Value = true;

    /*
     * Second method : Add control to the host in the cell
     */
    DateTimePicker dtp = new DateTimePicker();
    dtp.Value = DateTime.Now.AddDays(-10);
    //add DateTimePicker into the control collection of the DataGridView
    this.dataGridView1.Controls.Add(dtp);
    //set its location and size to fit the cell
    dtp.Location = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Location;
    dtp.Size = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Size;
}

Solution 2

The other answers are way to difficult and error prone. It is way easier to add the required cell type upon request.

Example:

Using the designer, create a form with a DataGridView, and two columns: one for the question and one for the answer.

private DataGridView dataGridView3;
private DataGridViewTextBoxColumn columnQuestion;
private DataGridViewTextBoxColumn columnAnswer;

In my class, I created the enum for the answer type

public enum AnswerType
{
    Text,
    YesNo,
    LoadFile,
    Combo,              
};

I create two methods: one to create a cell that contains a question, and one to create the proper cell type for the answer.

The method to create a question cell is simple:

private DataGridViewCell CreateQuestionCell(string question)
{
    return new DataGridViewTextBoxCell()
    {
        ValueType = typeof(string),
        Value = question,
        ReadOnly = true,       // questions can't be edited
    };
}

The method to create an answer cell has a parameter indicating the desired answer type:

private DataGridViewCell CreateAnswerCell(AnswerType answerType)
{
    // type of column depends on rowIndex
    DataGridViewCell cell;
    switch (answerType)
    {
        case AnswerType.YesNo: // Create a checkbox cell
            cell = new DataGridViewCheckBoxCell()
            {
                ValueType = typeof(bool),
                Value = false,
            };
            break;
        case AnswerType.LoadFile: // Create a Button cell
            cell = new DataGridViewButtonCell()
            {
                ValueType = typeof(string),
                Value = "Load!",
            };
            break;
        case AnswerType.Combo: // Create a Combo Cell
            var selectableValues = Enumerable.Range(0, 4);
            var comboItems = Enumerable.Range(0, 100);
            cell = new DataGridViewComboBoxCell()
            {
                DataSource = new BindingList<int>(comboItems.ToList()),
            };
            break;
        default: // Create a Text cell
            cell = new DataGridViewTextBoxCell()
            {
                ValueType = typeof(string),
                Value = "<please enter name>",
            };
            break;
    }
    return cell;
}

Upon request add a Row, containing a question cell and an answer cell:

private void AddRow(string question, AnswerType answerType)
{
    DataGridViewRow row = new DataGridViewRow();
    row.Cells.Add(this.CreateQuestionCell(question));
    row.Cells.Add(this.CreateAnswerCell(answerType));
    this.dataGridView1.Rows.Add(row);
}

To test I created four buttons and handlers to add rows:

private Button buttonCheckbox;
private Button buttonAction;
private Button buttonCombo;
private Button buttonText;

private void OnButtonCheckbox(object sender, EventArgs e)
{
    this.AddRow("Do you smoke", AnswerType.YesNo);
}

private void OnButtonText(object sender, EventArgs e)
{
    this.AddRow("Name", AnswerType.Text);
}

private void OnButtonCombo(object sender, EventArgs e)
{
    this.AddRow("Age?", AnswerType.Combo);
}

private void OnButtonAction(object sender, EventArgs e)
{
    this.AddRow("Document upload", AnswerType.LoadFile);
}

Et voilà, ça marche! Simple comme bonjour!

Solution 3

DataGridViewCellStyle styl_Column = new DataGridViewCellStyle();
         if (_myColumnCollection[i].TypeColumn == TypColumn.CheckBox)
                {
                   dtv_information.Columns.Add(chk_clmn);
                   styl_Column.NullValue = false;

                }
styl_Column.NullValue = false;
Share:
34,134
Alex
Author by

Alex

Updated on July 05, 2022

Comments

  • Alex
    Alex almost 2 years

    Goal

    My datagridview has two columns ([Question], [Answer]). Depending on the known question type (Yes/No Checkbox, Text Textbox, FileUpload Button) I want the column cell to have the respective control.

    Example

    Datagridview Rows:

    1. [Question] Do you smoke? [Answer] (YesNo Checkbox)
    2. [Question] How old are you? [Answer] (Text Textbox)
    3. [Question] Document upload [Answer] (FileUpload Button)

    Work

    I programmatically create my datagridviews.

    Private Sub FormatQuestionDgv(ByVal dgv As DataGridView)
        Dim ColQ As New DataGridViewTextBoxColumn
        Dim ColA As New DataGridViewColumn
    
        'Header text
        ColQ.HeaderText = "Question"
        ColA.HeaderText = "Answer"
    
        'Name
        ColQ.Name = "ColQ"
        ColA.Name = "ColA"
    
        'Widths
        ColQ.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
        ColA.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
    
        'Add columns
        With dgv.Columns
            .Add(ColQ)
            .Add(ColA)
        End With
    End Sub
    

    Problem

    As you can see in my work, the answer column is of DataGridViewColumn type. I do not know the question type at that moment. Therefore I declare it as a normal column instead of DataGridViewCheckBoxColumn, DataGridViewTextBoxColumn, DataGridViewButtonColumn...

    Since those are not the same type as DataGridViewColumn, I get the following error:

    Wrong Type Error

    How do I go about adding different control types in 1 DataGridViewColumn? Is it even possible?