Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Datagridview binding to 2 sources
 

Datagridview binding to 2 sources

i have a datagridview, i need to fill it with data coming from 2 different sources.
i want to get 1 column using binding from a table in database(first datasource). And in the other column i need to have comboboxs, all the combobox will be binded to a single source(second datasource), also i need some special logic to manipulate binding in the comboboxes, the idea is that i want that if user choose an element from one of these combobox, the element will be removed from the selection for others comboboxs, and when he choose another item the old item will return to the datasource.

I need some guidlines from experts here, or maybe someone did something similar can help in this.

Thanks in advance
Bruno_1  Tuesday, March 18, 2008 5:54 AM

Hi Bruno_1,

If you have two DataGridViewTextBoxColumns and want to bind each of them separately to a data source, there is no way to do this. You need to set DataGridView.VirtualMode property to true and populate the data by yourself.

However, your scenario is a bit special because the existence of a DataGridViewComboBoxColumn in your DataGridView control. You can set your DataGridView’s data source to your first data source and set DataGridViewComboBoxColumn’s data source to your second data source.

Your further requirement is difficult to implement. Once you bind the entire DataGridViewComboBoxColumn to one data source, all of the DataGridViewCombBoxCells are bind to that data source. Modification on the data source affects all the cells in that column. One way to walk around is to create a new ComboBoxCell and cover it on current DataGridViewComboBox being edited.

Code Snippet

partial class Form1 : Form

private BindingSource personsBindingSource = new BindingSource();

private BindingList<int> agesBindingList = new BindingList<int>();

private BindingList<int> promptedBindingList = new BindingList<int>();

private int oldValue = -1;

private void InitializeBindingSource()

typeof(Person);

new Person("Jacob", 10));

new Person("Johan", 20));

for (int i = 0; i < 10; i ++ )

promptedBindingList.Add(i);

private void Form1_Load(object sender, EventArgs e)

false;

DataGridViewTextBoxColumn firstTextBoxColumn = new DataGridViewTextBoxColumn();

"Name";

"Name";

"Name";

DataGridViewComboBoxColumn secondComboBoxColumn = new DataGridViewComboBoxColumn();

"Age";

"Age";

void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)

{

if (e.ColumnIndex == 1)

{

DataGridViewComboBoxCell cell = dataGridView1.CurrentCell as DataGridViewComboBoxCell;

if (cell.Value == null)

{

oldValue = -1;

}

else

{

oldValue = Int32.Parse(cell.Value.ToString());

} cell.Value = null;

cell.DataSource = promptedBindingList;

}

}

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)

{

if (e.ColumnIndex == 1)

{

DataGridViewComboBoxCell cell = dataGridView1.CurrentCell as DataGridViewComboBoxCell;

if (cell.Value != null)

{

int selectedValue = Int32.Parse(cell.Value.ToString());

int index = promptedBindingList.IndexOf(selectedValue);

promptedBindingList.RemoveAt(index);

if (oldValue != -1)

{

promptedBindingList.Add(oldValue);

oldValue = -1;

} cell.DataSource = agesBindingList;

index = agesBindingList.IndexOf(selectedValue);

cell.Value = agesBindingList[index];

}

else

{

if (oldValue != -1)

{

promptedBindingList.Add(oldValue);

oldValue = -1;

}

cell.DataSource = agesBindingList;

}

}

}

Code Snippet

class Person

private String m_name;

private int m_weight;

public String Name

get

return m_name;

set

value;

public int Weight

get

return m_weight;

set

value;

public Person()

"";

public Person(String aName, int theWeight)

Best regards,

Jacob

Jacob Sui - MSFT  Thursday, March 20, 2008 3:46 AM

Hi Bruno_1,

If you have two DataGridViewTextBoxColumns and want to bind each of them separately to a data source, there is no way to do this. You need to set DataGridView.VirtualMode property to true and populate the data by yourself.

However, your scenario is a bit special because the existence of a DataGridViewComboBoxColumn in your DataGridView control. You can set your DataGridView’s data source to your first data source and set DataGridViewComboBoxColumn’s data source to your second data source.

Your further requirement is difficult to implement. Once you bind the entire DataGridViewComboBoxColumn to one data source, all of the DataGridViewCombBoxCells are bind to that data source. Modification on the data source affects all the cells in that column. One way to walk around is to create a new ComboBoxCell and cover it on current DataGridViewComboBox being edited.

Code Snippet

partial class Form1 : Form

private BindingSource personsBindingSource = new BindingSource();

private BindingList<int> agesBindingList = new BindingList<int>();

private BindingList<int> promptedBindingList = new BindingList<int>();

private int oldValue = -1;

private void InitializeBindingSource()

typeof(Person);

new Person("Jacob", 10));

new Person("Johan", 20));

for (int i = 0; i < 10; i ++ )

promptedBindingList.Add(i);

private void Form1_Load(object sender, EventArgs e)

false;

DataGridViewTextBoxColumn firstTextBoxColumn = new DataGridViewTextBoxColumn();

"Name";

"Name";

"Name";

DataGridViewComboBoxColumn secondComboBoxColumn = new DataGridViewComboBoxColumn();

"Age";

"Age";

void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)

{

if (e.ColumnIndex == 1)

{

DataGridViewComboBoxCell cell = dataGridView1.CurrentCell as DataGridViewComboBoxCell;

if (cell.Value == null)

{

oldValue = -1;

}

else

{

oldValue = Int32.Parse(cell.Value.ToString());

} cell.Value = null;

cell.DataSource = promptedBindingList;

}

}

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)

{

if (e.ColumnIndex == 1)

{

DataGridViewComboBoxCell cell = dataGridView1.CurrentCell as DataGridViewComboBoxCell;

if (cell.Value != null)

{

int selectedValue = Int32.Parse(cell.Value.ToString());

int index = promptedBindingList.IndexOf(selectedValue);

promptedBindingList.RemoveAt(index);

if (oldValue != -1)

{

promptedBindingList.Add(oldValue);

oldValue = -1;

} cell.DataSource = agesBindingList;

index = agesBindingList.IndexOf(selectedValue);

cell.Value = agesBindingList[index];

}

else

{

if (oldValue != -1)

{

promptedBindingList.Add(oldValue);

oldValue = -1;

}

cell.DataSource = agesBindingList;

}

}

}

Code Snippet

class Person

private String m_name;

private int m_weight;

public String Name

get

return m_name;

set

value;

public int Weight

get

return m_weight;

set

value;

public Person()

"";

public Person(String aName, int theWeight)

Best regards,

Jacob

Jacob Sui - MSFT  Thursday, March 20, 2008 3:46 AM
Thanks i only today checked the answer, and it was exactly what i wanted, i hoped i can double marked answered Smile, there is only one little thing missing on the cellbeginedit event, i should add the current element available in the cell to the promptedbinding list before entering the edit.

Also i have some questions, i hope you can help me with them:
1 - if i removed the cell begin edit and the cell end edit, i got an error : system.argumentexception: datagridviewcomboboxcellvalue is not valid, i am not sure why it is happening (maybe something in incompatible type or casting between string and int ?).
2 - why you set call.value = null before binding to promptedlist in the begin edit event ? (i know it is needed since it makes the same problem as above without it

Thanks !

Bruno_1  Wednesday, April 02, 2008 12:44 AM

Hi Bruno_1,

1. I made a mistake. Once a DataGridView’s DataSource property is set, columns of that DataGridView shouldn’t be bound to any other data source. What I wrote in the Form1_Load method is incorrect.

Code Snippet

DataGridViewComboBoxColumn secondComboBoxColumn = new DataGridViewComboBoxColumn();

secondComboBoxColumn.Name = "Age";

secondComboBoxColumn.HeaderText = "Age";

// Attention! The following line is illegal, comment it out

//secondComboBoxColumn.DataSource = agesBindingList;

dataGridView1.Columns.Add(secondComboBoxColumn);

With the above line commented out, the program still runs and gives you what you want.

2. If you delete cell.value = null and do the following

· Select one value in the first ComboBox.

· Select another value in the second ComboBox.

· Go back to the first ComboBox and click the arrow in the first ComboBox to bring down the drop down menu.

An error will occur when the drop down menu of the first ComboBox is showing.

The reason is that when you go back to the first ComboBox, the value displayed in the ComboBox (say 2) does not exist in the data source (say, 1, 3, 4, �, 9, 0). The ComboBox thinks that if its DataSource is bound, the value inside the ComboBox should exist in the DataSource. One way to walk around is to set the ComboBox’s DataSource property to null, allowing the ComboBox to show a value temporarily.

Best regards,

Jacob

Jacob Sui - MSFT  Wednesday, April 02, 2008 2:35 AM

i hava a proble like this

system.ArgumentException DatagridviewComboboxcellvalue is not valid

when i fill the datagrid dynamically with sqlsever 2005

kindly give any possible solution

ThankI will be thank full

imran_sms  Wednesday, August 06, 2008 9:20 AM

You can use google to search for other answers

Custom Search

More Threads

• Bound ComboBox are automatically selecting the first item
• Combo Box Error - Too Many items in the combo box
• ComboBox Binding Problem
• Copy the Records from one Table to another Table
• DataGridView BeginEdit Locks
• newly added row to datagridview not visible
• Finding values in a databound combobox
• custom painting on datagridview
• Using AddingNew eventhandler to set defaults
• Conditional RowStyle on databound DataGridView