views:

1362

answers:

3

I want to have a DataGridView that has two columns. The first column will always be of type DataGridViewComboBoxColumn. Based on the selection in that column, I'd like to be able to change the corresponding cell in the second column to either a DataGridViewComboBoxCell or a DataGridViewTextBoxCell.

I'm thinking I just need to make the second column of type DataGridViewColumn, but don't understand the mechanics of how to change the cell type on the fly.

I'm working with VB.NET in Visual Studio 2005.

Thanks in advance!

Update: One way around it, I suppose, is to make the second column as a DataGridViewComboBoxColumn, and change the attributes of the cell so that it either behaves like a drop-down list, or as an (editable) drop-down with no elements. The latter looks enough like a text box that I could live with it, and it wouldn't involve changing the type of the cell.

+1  A: 

I don't have the VB.Net version,but hopefully this quick C# snippet will help you or point you in the right direction.

In this example, I set up a simple DataGridView with 2 columns. The first being a DataGridViewComboBox populated with two choices: "Text" or "Combo".

The second column is initially set to DataGridViewTextBoxColumn from the designer.

I handle the CurrentCellDirtyStateChanged event on the DataGridView. I check if the cell is dirty and only check the first column (The ComboBox). You gotta call the CommitEdit to get the new value in the combo or else you will be looking at the previous value. Based on the selection in the combo box I then overwrite the cell in the 2nd column with a new cell of that type.

You would add your own logic (populate the drop downs and handle the value). You might want to store the value and then put it back into the cell or whatever.

Here is the code I used and did a quick and dirty test on:

private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (dataGridView1.IsCurrentCellDirty == false)
        {
            return;
        }

        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);

        if (dataGridView1.CurrentCell.ColumnIndex == 0)
        {               
            if (((string)dataGridView1.CurrentCell.Value) == "Text")
            {
                dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewTextBoxCell();
            }
            else if (((string)dataGridView1.CurrentCell.Value) == "Combo")
            {
                dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewComboBoxCell();
            }
        }
    }

Here is a quick VB translation, that I tested and works.

Public Class Form1

Private Sub DataGridView1_CurrentCellDirtyStateChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged

    If DataGridView1.IsCurrentCellDirty = False Then
        Return
    End If

    DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)

    If DataGridView1.CurrentCell.ColumnIndex = 0 Then

        If CStr(DataGridView1.CurrentCell.Value) = "Text" Then
            DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewTextBoxCell

        ElseIf CStr(DataGridView1.CurrentCell.Value) = "Combo" Then
            DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewComboBoxCell
        End If

    End If


End Sub

End Class

You will lose any value stored in that column, so you would need to save it first.

Jon

jomtois
Thank you. This is helpful. I'm not really a VB or a .NET expert so I see what you're doing in principle, but the mechanics of allocating a new DataGridViewTextBoxCell or a new DataGridViewComboBoxCell in VB are something I'll still have to figure out. In any case I appreciate the time you've put into your answer, and I'll try it this afternoon.
John at CashCommons
Works great. Thank you!
John at CashCommons
+2  A: 

You can create your own cell template that hosts a user control. In the user control you add a textbox and a combobox, and add a method/property to show one and hide another.

This sample creates a radio button cell, it is not hard to change the code to host a user control.

Sheng Jiang 蒋晟
Thanks for your response. Appreciate it!
John at CashCommons
A: 

Hi, I tried doing as you mentioned above but it was giving a casting error to me

Unable to cast object of type DataGridViewTextBoxColumn to type DataGridViewComboBoxColumn. My code is:

                DataGridViewComboBoxCell cellcombo = new DataGridViewComboBoxCell();
                cellcombo.DataSource = populateDropDowns();
                dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] = cellcombo;

Is there anything I am doing wrong?

Jay
Welcome to StackOverflow! Even though this is related to the topic at hand, it would be better to pose this as a new question. You'll likely get more people looking at this issue.
John at CashCommons