ComboBox selection generating list for another comboBox question
-
Guess who. I have the following:
private void column1DataGridViewComboBox_SelectedIndexChanged(object sender, EventArgs e)
{ComboBox cb = sender as ComboBox; string strPrimary = cb.SelectedItem.ToString(); Debug.WriteLine(strPrimary); var dataSource = new List<Units>(); switch (strPrimary) { case "1": //Build a list dataSource.Add(new Units() { Unit = "blah1" }); dataSource.Add(new Units() { Unit = "blah2" }); dataSource.Add(new Units() { Unit = "blah3" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case "2": //Build a list dataSource.Add(new Units() { Unit = "blah4" }); dataSource.Add(new Units() { Unit = "blah5" }); dataSource.Add(new Units() { Unit = "blah6" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case "3": //Build a list dataSource.Add(new Units() { Unit = "blah7" }); dataSource.Add(new Units() { Unit = "blah8" }); dataSource.Add(new Units() { Unit = "blah9" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; } }
Well, the problem of course as you know is that ComboBox cb points to the second comboBox once I select it. In fact, once I select a value on the first comboBox and then select the second comboBox to select a value, debug.writeline gives me "WindowsFormsApplication1.Form1+Units" (although the 2nd comboBox does get populated with the appropriate list based upon the selection of the first comboBox). If I use an integer instead of strPrimary and set it as cb.SelectedIndex, what I actually get from debug is the index of the selection of the list of the second comboBox (eg if blah5 is selected, I get an integer = 1) followed by an integer
Aaaaand relax! I think I know what is going on here. If you recall, well even if you don't recall actually :) , in my second message to you I had this bit of code: (I've annotated it a bit and modified it v,v slightly)
private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; // switch (dataGrid.CurrentCell.ColumnIndex) <===================================== silly! already have column in eventargs switch (e.Column) //<==============================Use this instead { case 0: // use the index for your comboboxcolumn <============ **V IMPORTANT** make sure that the 0: matches the index for your column cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.SelectedIndexChanged -= column1DataGridViewComboBox\_SelectedIndexChanged; // now attach the event handler cb.SelectedIndexChanged += column1DataGridViewComboBox\_SelectedIndexChanged; } break; // <================================== You do not need the part below since you only need it to apply to the first cbcolumn //case 3: // use the index for your second combo // cb = e.Control as ComboBox; // if (cb != null) //{ // first remove event handler to keep from attaching multiple: // cb.SelectedIndexChanged -= cb\_SecondSelectedIndexChanged; // now attach the event handler // cb.SelectedIndexChanged += cb\_SecondSelectedIndexChanged; //} //break; } }
If you can absolutely guarantee that you will only want to do this for one
ComboBoxColumn
you can simplify the code slightly.private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; // replace the switch statement by an if statement if (e.Column == 0) //<============ **V IMPORTANT** change the 0 (if necessary) to match the index for your column { cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.Selec
-
Aaaaand relax! I think I know what is going on here. If you recall, well even if you don't recall actually :) , in my second message to you I had this bit of code: (I've annotated it a bit and modified it v,v slightly)
private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; // switch (dataGrid.CurrentCell.ColumnIndex) <===================================== silly! already have column in eventargs switch (e.Column) //<==============================Use this instead { case 0: // use the index for your comboboxcolumn <============ **V IMPORTANT** make sure that the 0: matches the index for your column cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.SelectedIndexChanged -= column1DataGridViewComboBox\_SelectedIndexChanged; // now attach the event handler cb.SelectedIndexChanged += column1DataGridViewComboBox\_SelectedIndexChanged; } break; // <================================== You do not need the part below since you only need it to apply to the first cbcolumn //case 3: // use the index for your second combo // cb = e.Control as ComboBox; // if (cb != null) //{ // first remove event handler to keep from attaching multiple: // cb.SelectedIndexChanged -= cb\_SecondSelectedIndexChanged; // now attach the event handler // cb.SelectedIndexChanged += cb\_SecondSelectedIndexChanged; //} //break; } }
If you can absolutely guarantee that you will only want to do this for one
ComboBoxColumn
you can simplify the code slightly.private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; // replace the switch statement by an if statement if (e.Column == 0) //<============ **V IMPORTANT** change the 0 (if necessary) to match the index for your column { cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.Selec
Good morning (or whatever time of day it is to you). DataGridViewEditingControlShowingEventArgs does not contain the "column" method. I do remember your second message and did try to do that yesterday without success. Let me give you both methods together:
private void column1DataGridViewComboBox_SelectedIndexChanged(object sender, EventArgs e)
{ComboBox cb = sender as ComboBox; int intPrimary = cb.SelectedIndex; Debug.WriteLine(intPrimary + "SelectedIndexChanged"); var dataSource = new List<Units>(); switch (intPrimary) { case 0: //Build a list dataSource.Add(new Units() { Unit = "blah1" }); dataSource.Add(new Units() { Unit = "blah2" }); dataSource.Add(new Units() { Unit = "blah3" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case 1: //Build a list dataSource.Add(new Units() { Unit = "blah4" }); dataSource.Add(new Units() { Unit = "blah5" }); dataSource.Add(new Units() { Unit = "blah6" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case 2: //Build a list dataSource.Add(new Units() { Unit = "blah7" }); dataSource.Add(new Units() { Unit = "blah8" }); dataSource.Add(new Units() { Unit = "blah9" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; } } private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; Debug.WriteLine(dataGridView1.CurrentCell.ColumnIndex + "EditControlShowing"); switch (dataGridView1.CurrentCell.ColumnIndex) { case 0: cb = e.Contr
-
Good morning (or whatever time of day it is to you). DataGridViewEditingControlShowingEventArgs does not contain the "column" method. I do remember your second message and did try to do that yesterday without success. Let me give you both methods together:
private void column1DataGridViewComboBox_SelectedIndexChanged(object sender, EventArgs e)
{ComboBox cb = sender as ComboBox; int intPrimary = cb.SelectedIndex; Debug.WriteLine(intPrimary + "SelectedIndexChanged"); var dataSource = new List<Units>(); switch (intPrimary) { case 0: //Build a list dataSource.Add(new Units() { Unit = "blah1" }); dataSource.Add(new Units() { Unit = "blah2" }); dataSource.Add(new Units() { Unit = "blah3" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case 1: //Build a list dataSource.Add(new Units() { Unit = "blah4" }); dataSource.Add(new Units() { Unit = "blah5" }); dataSource.Add(new Units() { Unit = "blah6" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; case 2: //Build a list dataSource.Add(new Units() { Unit = "blah7" }); dataSource.Add(new Units() { Unit = "blah8" }); dataSource.Add(new Units() { Unit = "blah9" }); //Setup data binding this.column2DataGridViewComboBox.DataSource = dataSource; this.column2DataGridViewComboBox.DisplayMember = "Unit"; break; } } private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; Debug.WriteLine(dataGridView1.CurrentCell.ColumnIndex + "EditControlShowing"); switch (dataGridView1.CurrentCell.ColumnIndex) { case 0: cb = e.Contr
mprice214 wrote:
DataGridViewEditingControlShowingEventArgs does not contain the "column" method.
:-D That's what you get for trying to code off the top of your head. Good to see that you were smart enough to use the correct form.:thumbsup: Once again I think I have worked out what is happening. In order to save on system resources, dear old M$ are using the same
ComboBox
for allComboBoxCell
s and just hiding it, rather than destroying it, when not needed. Because it is just hidden, the link to theSelectedIndexChanged
never gets deleted, which is why it occurs for column2 as well. After very little thought I see three ways to handle the problem: 1. in theSelectedIndexChanged
handler test for the column index before anything else and bomb out (a technical term :) ) if not the one we want.private void column1DataGridViewComboBox\_SelectedIndexChanged(object sender, EventArgs e) { if (dataGridView1.CurrentCell.ColumnIndex != 0) // <=========== Bombing out construct { return; } ComboBox cb = sender as ComboBox; int intPrimary = cb.SelectedIndex; Debug.WriteLine(intPrimary + "SelectedIndexChanged"); ................................ ................................ ................................ ................................ }
2. in the
EditingControlShowing
handler remove the link when we don't find the column we want.private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; Debug.WriteLine(dataGridView1.CurrentCell.ColumnIndex + "EditControlShowing"); switch (dataGridView1.CurrentCell.ColumnIndex) { case 0: cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.SelectedIndexChanged -= column1DataGridViewComboBox\_SelectedIndexChanged; // now attach the event handler cb.SelectedIndexChanged += column1DataGridViewComboBox\_SelectedIndexChanged; } break; default:
-
mprice214 wrote:
DataGridViewEditingControlShowingEventArgs does not contain the "column" method.
:-D That's what you get for trying to code off the top of your head. Good to see that you were smart enough to use the correct form.:thumbsup: Once again I think I have worked out what is happening. In order to save on system resources, dear old M$ are using the same
ComboBox
for allComboBoxCell
s and just hiding it, rather than destroying it, when not needed. Because it is just hidden, the link to theSelectedIndexChanged
never gets deleted, which is why it occurs for column2 as well. After very little thought I see three ways to handle the problem: 1. in theSelectedIndexChanged
handler test for the column index before anything else and bomb out (a technical term :) ) if not the one we want.private void column1DataGridViewComboBox\_SelectedIndexChanged(object sender, EventArgs e) { if (dataGridView1.CurrentCell.ColumnIndex != 0) // <=========== Bombing out construct { return; } ComboBox cb = sender as ComboBox; int intPrimary = cb.SelectedIndex; Debug.WriteLine(intPrimary + "SelectedIndexChanged"); ................................ ................................ ................................ ................................ }
2. in the
EditingControlShowing
handler remove the link when we don't find the column we want.private void dataGridView1\_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cb; Debug.WriteLine(dataGridView1.CurrentCell.ColumnIndex + "EditControlShowing"); switch (dataGridView1.CurrentCell.ColumnIndex) { case 0: cb = e.Control as ComboBox; if (cb != null) { // first remove event handler to keep from attaching multiple: cb.SelectedIndexChanged -= column1DataGridViewComboBox\_SelectedIndexChanged; // now attach the event handler cb.SelectedIndexChanged += column1DataGridViewComboBox\_SelectedIndexChanged; } break; default:
Thanks for your help on this. I was able to become much more familiar with the event handlers. I began focusing on DataGridView FAQ Appendix A, 18 that you mentioned a bit ago. I was trying to get that going and was still having some issues and then came across http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/6f6c2632-afd7-4fe9-8bf3-c2c8c08d1a31/[^] Anyway, I'll have to tweak it a bit to keep users from pulling down the second comboBox first (which will throw and exception), but it's exactly what I need. Anyway, you taking the time really helped me out to understand some "basic" things that will help me get through the rest of this project. Thanks again.
public partial class Form1 : Form
{
DataTable tblPrimary, tblSecondary;
BindingSource primaryBS, filteredSecondaryBS, unfilteredSecondaryBS;public Form1() { tblPrimary = new DataTable("Primary"); tblPrimary.Columns.Add("ID", typeof(int)); tblPrimary.Columns.Add("Name", typeof(string)); tblSecondary = new DataTable("Secondary"); tblSecondary.Columns.Add("ID", typeof(int)); tblSecondary.Columns.Add("subID", typeof(int)); tblSecondary.Columns.Add("Name", typeof(string)); tblPrimary.Rows.Add(new object\[\] { 0, "Force" }); tblPrimary.Rows.Add(new object\[\] { 1, "Torque" }); tblPrimary.Rows.Add(new object\[\] { 2, "Pressure" }); tblSecondary.Rows.Add(new object\[\] { 0, 0, "lb" }); tblSecondary.Rows.Add(new object\[\] { 1, 0, "N" }); tblSecondary.Rows.Add(new object\[\] { 2, 0, "oz" }); tblSecondary.Rows.Add(new object\[\] { 3, 1, "in-lb" }); tblSecondary.Rows.Add(new object\[\] { 4, 1, "ft-lb" }); tblSecondary.Rows.Add(new object\[\] { 5, 1, "N-m" }); tblSecondary.Rows.Add(new object\[\] { 6, 2, "PSI" }); tblSecondary.Rows.Add(new object\[\] { 7, 2, "Pa" }); tblSecondary.Rows.Add(new object\[\] { 8, 2, "bar" }); InitializeComponent(); primaryBS = new BindingSource(); primaryBS.DataSource = tblPrimary;