Datagridview comboboxcolumn different values ​​for each row

I want to create a datagridview with comboboxcolumns using C #.

The problem is I don't know how to give different values ​​for the combobox on each line.

DataTable dt = new DataTable();
dt.Columns.Add("state");
dt.Columns.Add("city");
dt.Rows.Add("a1", "b1");
dt.Rows.Add("a1", "b2");
dt.Rows.Add("a2", "b3");
dt.Rows.Add("a2", "b4");
dt.Rows.Add("a3", "b5");
DataGridViewComboBoxColumn comboStates = new DataGridViewComboBoxColumn();
comboStates.HeaderText = "HeaderText_1";
this.dataGridView1.Columns.Insert(0, comboStates);
DataGridViewComboBoxColumn comboCities = new DataGridViewComboBoxColumn();
comboCities.HeaderText = "HeaderText_2";
this.dataGridView1.Columns.Insert(1, comboCities);

for (int i = 0; i < dt.Rows.Count; i++)
{
    dataGridView1.Rows.Add();
    comboStates.Items.Add(dt.Rows[i][0]);
        DataGridViewComboBoxCell stateCell = (DataGridViewComboBoxCell)    (dataGridView1.Rows[i].Cells[0]);
    stateCell.Value = comboStates.Items[i];
    comboCities.Items.Add(dt.Rows[i][1]);
    DataGridViewComboBoxCell cityCell = (DataGridViewComboBoxCell)(dataGridView1.Rows[i].Cells[1]);
    cityCell.Value = comboCities.Items[i];
}

      

This example shows the following results:

for each line:

comboboxcolumnstate:

a1
a1
a2
a2
a3

      

comboboxcolumncity:

b1
b2
b3
b4
b5

      

I know this is ok because I am looping through the data through the datatable.

So how can I get this result:

row1: comboboxcolumnstate comboboxcolumncity

             a1               b1 - b2

      

row2: comboboxcolumnstate comboboxcolumncity

             a2               b3 - b4

      

row2: comboboxcolumnstate comboboxcolumncity

             a3               b5

      

I am new to C #. I have searched a lot, but I have not found a solution that solves this problem. thank

+3


source to share


1 answer


Here's some sample code that should get you started.

First, I create a list of values ​​(cities) for each state. For this, the collection is Dictionary

convenient:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();

for (int i = 0; i < dt.Rows.Count; i++)
{
    string state = dt.Rows[i][0].ToString();
    string city  = dt.Rows[i][1].ToString();

    if (! dict.Keys.Contains(state ))  dict.Add(state, new List<string>());
    dict[state].Add(city);
}

      

I loop over your table, and for each row, I add a new entry for city and, if necessary, for state.

We will now change the DGV setting to use the ones Lists

in Items

each DataGridViewComboBoxCell

.

Note: here the key must use DataGridViewComboBoxCells

and not DataGridViewComboBoxColumns

!

For ease of access, I again create string variables for the state and city values.



for (int i = 0; i < dt.Rows.Count; i++)
{
    string state = dt.Rows[i][0].ToString();
    string city = dt.Rows[i][1].ToString();
    dataGridView1.Rows.Add();
    DataGridViewComboBoxCell stateCell = 
                            (DataGridViewComboBoxCell)(dataGridView1.Rows[i].Cells[0]);
    stateCell.Items.AddRange(dict.Keys.ToArray());
    stateCell.Value = state;
    DataGridViewComboBoxCell cityCell = 
                            (DataGridViewComboBoxCell)(dataGridView1.Rows[i].Cells[1]);
    cityCell.Items.AddRange(dict[state].ToArray());
    cityCell.Value = city;
}

      

Note. This sets the values ​​to DropDowns, but after every change in the "State" column, you will need to adapt the "Cities" column in that row! So it would be a good idea to make it Dictionary

permanent by moving it to the class level and create a small function that you can call after such a change.

Here's an example of this function:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == 0)
        setCities(e.RowIndex, dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString());
}

void setCities(int row, string state)
{
    DataGridViewComboBoxCell cityCell = 
                           (DataGridViewComboBoxCell)(dataGridView1.Rows[row].Cells[1]);
    cityCell.Items.Clear();
    cityCell.Items.AddRange(dict[state].ToArray());
    cityCell.Value = cityCell.Items[0];
}

      

Please note that the new one cityCell.Value

appears only after exiting the edited cell!

Final note. If you really only want to display one row for each state, you need to change the loop that fills DGV

in so that the loop is not over your table, but through the collection dict.Keys

:

for (int i = 0; i <  dict.Keys.Count; i++)
{
    string state = dict.Keys.ElementAt(i);
    string city1 = dict[state][0].ToString();
    dataGridView1.Rows.Add();
    DataGridViewComboBoxCell stateCell = 
                            (DataGridViewComboBoxCell)(dataGridView1.Rows[i].Cells[0]);
    stateCell.Items.AddRange(dict.Keys.ToArray());
    stateCell.Value = state;
    DataGridViewComboBoxCell cityCell = 
                            (DataGridViewComboBoxCell)(dataGridView1.Rows[i].Cells[1]);
    cityCell.Items.AddRange(dict[state].ToArray());
    cityCell.Value = city1;
}

      

+5


source







All Articles