Change DataSource for a ComboBox CELL

I have a DataGridView control that has a couple of ComboBox columns. These columns are populated by a bound DataSource. I'd like to alter the DataSource of the ComboBox control in the cell in column 2 in response to a selection in column 1. This code allows me to hook the SelectedIndexChanged event of the ComboBox in column 1.

http://stackoverflow.com/questions/5652957/what-event-catches-a-change-of-value-in-a-combobox-in-a-datagridviewcell

My question is, is it possible to change the DataSource of the ComboBox in the next cell? I haven't found a way to access the actual ComboBox control. I can only seem to access the cell.

Question rephrased: Is it possible to get the actual Control contained within a DataGridViewCell?
LVL 21
Russ SuterAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Najam UddinCommented:
Did you tried getting
DataGridViewComboBoxColumn col1 = YourGridView.Columns[index] as DataGridViewComboBoxColumn ;

Open in new window

0
Russ SuterAuthor Commented:
That only gets me the column. What I need is the instance of the ComboBox control in an individual cell.
0
Najam UddinCommented:
You can assign datasource property of this coumn of type DataGridViewComboBoxColumn
0
Russ SuterAuthor Commented:
Please re-read my original question. I need to update the DataSource property of the ComboBox in an individual Cell and not for the entire column.
0
it_saigeDeveloperCommented:
A relatively simplistic approach:

Form1.cs -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace EE_Q28810140
{
	public partial class Form1 : Form
	{
		readonly List<Fruit> fruits = new List<Fruit>() { new Fruit() { ID = 0, Name = "Apple" }, new Fruit() { ID = 1, Name = "Bannana" }, new Fruit() { ID = 2, Name = "Cherry" } };
		readonly List<Vegetable> vegetables = new List<Vegetable>() { new Vegetable() { ID = 0, Name = "Asparagus" }, new Vegetable() { ID = 1, Name = "Beet" }, new Vegetable() { ID = 2, Name = "Corn" } };
		readonly List<Item> delicacies = new List<Item>() { new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() } };
		bool isLoading;

		public Form1()
		{
			isLoading = true;
			InitializeComponent();
			dataGridView1.DataSource = delicacies;
			Column1.DataSource = Enum.GetNames(typeof(DelicacyType));
			isLoading = false;
		}

		private void OnCellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			if (!isLoading)
			{
				if (sender is DataGridView)
				{
					var dgv = sender as DataGridView;
					if (dgv.Rows.Count > 0)
					{
						if (dgv.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
						{
							var currentCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewComboBoxCell;
							var nextCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex + 1] as DataGridViewComboBoxCell;
							var data = (dgv.Rows[e.RowIndex] as DataGridViewRow).DataBoundItem as Item;
							if (currentCell.ColumnIndex.Equals(0))
							{
								nextCell.DisplayMember = "Name";
								nextCell.ValueMember = "ID";
								switch ((DelicacyType)Enum.Parse(typeof(DelicacyType), currentCell.Value.ToString()))
								{
									case DelicacyType.Fruit:
										nextCell.DataSource = fruits;
										data.Type = DelicacyType.Fruit;
										break;
									case DelicacyType.Vegetable:
										nextCell.DataSource = vegetables;
										data.Type = DelicacyType.Vegetable;
										break;
									case DelicacyType.None:
									default:
										break;
								}
							}
							else
							{
								data.Delicacy = (from item in currentCell.Items.Cast<Delicacy>().ToList() where item.ID.Equals(currentCell.Value) select item).FirstOrDefault();
							}
						}
						dgv.Refresh();
					}
				}
			}
		}

		private void OnDataError(object sender, DataGridViewDataErrorEventArgs e)
		{
		}

		private void OnCurrentCellDirtyStateChanged(object sender, EventArgs e)
		{
			if (!isLoading)
			{
				if (sender is DataGridView)
				{
					var dgv = sender as DataGridView;
					if (dgv.Rows.Count > 0 && dgv.IsCurrentCellDirty)
					{
						dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
						dgv.Refresh();
					}
				}
			}
		}
	}

	class Item
	{
		public DelicacyType Type { get; set; }
		public Delicacy Delicacy { get; set; }
	}

	enum DelicacyType : int
	{
		None = 0,
		Fruit = 1,
		Vegetable = 2
	}

	class Delicacy 
	{ 
		public virtual int ID { get; set; }
		public virtual string Name { get; set; }
		public override string ToString()
		{
			return Name;
		}
	}

	class Fruit : Delicacy { }

	class Vegetable : Delicacy { }
}

Open in new window

Form1.Designer.cs -
namespace EE_Q28810140
{
	partial class Form1
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.dataGridView1 = new System.Windows.Forms.DataGridView();
			this.Column1 = new System.Windows.Forms.DataGridViewComboBoxColumn();
			this.Column2 = new System.Windows.Forms.DataGridViewComboBoxColumn();
			((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
			this.SuspendLayout();
			// 
			// dataGridView1
			// 
			this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
			this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            this.Column1,
            this.Column2});
			this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.dataGridView1.Location = new System.Drawing.Point(0, 0);
			this.dataGridView1.Name = "dataGridView1";
			this.dataGridView1.Size = new System.Drawing.Size(594, 261);
			this.dataGridView1.TabIndex = 0;
			this.dataGridView1.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.OnCellValueChanged);
			this.dataGridView1.CurrentCellDirtyStateChanged += new System.EventHandler(this.OnCurrentCellDirtyStateChanged);
			this.dataGridView1.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.OnDataError);
			// 
			// Column1
			// 
			this.Column1.HeaderText = "Select Type";
			this.Column1.Name = "Column1";
			// 
			// Column2
			// 
			this.Column2.HeaderText = "Select Delicacy";
			this.Column2.Name = "Column2";
			// 
			// Form1
			// 
			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			this.ClientSize = new System.Drawing.Size(594, 261);
			this.Controls.Add(this.dataGridView1);
			this.Name = "Form1";
			this.Text = "Form1";
			((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
			this.ResumeLayout(false);

		}

		#endregion

		private System.Windows.Forms.DataGridView dataGridView1;
		private System.Windows.Forms.DataGridViewComboBoxColumn Column1;
		private System.Windows.Forms.DataGridViewComboBoxColumn Column2;
	}
}

Open in new window

Produces the following ouput -Initial launchSelect Type drop down is populated.  As it is initially blank, the Select Delicacy drop down has no entries.Changing between the types "Fruit" and "Vegetable" populate the drop down for delicacy.
And in case the question comes up, yes this is cell specific.

Proof of concept:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace EE_Q28810140
{
	public partial class Form1 : Form
	{
		readonly List<Fruit> fruits = new List<Fruit>() { new Fruit() { ID = 0, Name = "Apple" }, new Fruit() { ID = 1, Name = "Bannana" }, new Fruit() { ID = 2, Name = "Cherry" } };
		readonly List<Vegetable> vegetables = new List<Vegetable>() { new Vegetable() { ID = 0, Name = "Asparagus" }, new Vegetable() { ID = 1, Name = "Beet" }, new Vegetable() { ID = 2, Name = "Corn" } };
		readonly List<Item> delicacies = new List<Item>() { new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() }, new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() }, new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() }, new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() }, new Item() { Type = DelicacyType.Fruit, Delicacy = new Fruit() } };
		bool isLoading;

		public Form1()
		{
			isLoading = true;
			InitializeComponent();
			dataGridView1.DataSource = delicacies;
			Column1.DataSource = Enum.GetNames(typeof(DelicacyType));
			isLoading = false;
		}

		private void OnCellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			if (!isLoading)
			{
				if (sender is DataGridView)
				{
					var dgv = sender as DataGridView;
					if (dgv.Rows.Count > 0)
					{
						if (dgv.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
						{
							var currentCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewComboBoxCell;
							var nextCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex + 1] as DataGridViewComboBoxCell;
							var data = (dgv.Rows[e.RowIndex] as DataGridViewRow).DataBoundItem as Item;
							if (currentCell.ColumnIndex.Equals(0))
							{
								nextCell.DisplayMember = "Name";
								nextCell.ValueMember = "ID";
								switch ((DelicacyType)Enum.Parse(typeof(DelicacyType), currentCell.Value.ToString()))
								{
									case DelicacyType.Fruit:
										nextCell.DataSource = fruits;
										data.Type = DelicacyType.Fruit;
										break;
									case DelicacyType.Vegetable:
										nextCell.DataSource = vegetables;
										data.Type = DelicacyType.Vegetable;
										break;
									case DelicacyType.None:
									default:
										break;
								}
							}
							else
							{
								data.Delicacy = (from item in currentCell.Items.Cast<Delicacy>().ToList() where item.ID.Equals(currentCell.Value) select item).FirstOrDefault();
							}
						}
						dgv.Refresh();
					}
				}
			}
		}

		private void OnDataError(object sender, DataGridViewDataErrorEventArgs e)
		{
		}

		private void OnCurrentCellDirtyStateChanged(object sender, EventArgs e)
		{
			if (!isLoading)
			{
				if (sender is DataGridView)
				{
					var dgv = sender as DataGridView;
					if (dgv.Rows.Count > 0 && dgv.IsCurrentCellDirty)
					{
						dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
						dgv.Refresh();
					}
				}
			}
		}
	}

	class Item
	{
		public DelicacyType Type { get; set; }
		public Delicacy Delicacy { get; set; }
	}

	enum DelicacyType : int
	{
		None = 0,
		Fruit = 1,
		Vegetable = 2
	}

	class Delicacy 
	{ 
		public virtual int ID { get; set; }
		public virtual string Name { get; set; }
		public override string ToString()
		{
			return Name;
		}
	}

	class Fruit : Delicacy { }

	class Vegetable : Delicacy { }
}

Open in new window

Which now produces the following output -Choosing different options from each combobox.
-saige-
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.