Reputation: 87
I am working on a winforms project that contains a data grid view which has two combo box columns. My goal is to make the first combo box column show specific items that match with certain condition.
I researched the topic and found that I need to listen to DataGridView's EditingControlShowing event to detect when the user opens a combo box for display. Then I need to cast the sender object to ComboBox object and listen to MeasureItem & DrawItem events. Now, I'll be able to draw the items that meet the condition and hide the rest.
Here are my source links: 1, 2, 3, 4
First, here's my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataGridViewComboBoxColumn first_column = new DataGridViewComboBoxColumn();
first_column.Name = "First";
first_column.Items.Add("A");
first_column.Items.Add("B");
first_column.Items.Add("C");
first_column.Items.Add("D");
dataGridView1.Columns.Add(first_column);
DataGridViewComboBoxColumn second_column = new DataGridViewComboBoxColumn();
second_column.Name = "Second";
second_column.Items.Add("1");
second_column.Items.Add("2");
second_column.Items.Add("3");
second_column.Items.Add("4");
dataGridView1.Columns.Add(second_column);
dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
}
private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox comboBox = e.Control as ComboBox;
if (comboBox != null && dataGridView1.CurrentCell.ColumnIndex == 0)
{
comboBox.DrawItem -= ComboBox_DrawItem;
comboBox.DrawItem += ComboBox_DrawItem;
comboBox.MeasureItem -= ComboBox_MeasureItem;
comboBox.MeasureItem += ComboBox_MeasureItem;
comboBox.DrawMode = DrawMode.OwnerDrawVariable;
}
}
private void ComboBox_MeasureItem(object sender, MeasureItemEventArgs e)
{
if (sender is DataGridViewComboBoxEditingControl comboBox && dataGridView1.CurrentCell.ColumnIndex == 0)
{
if (!canDraw(e.Index))
{
e.ItemHeight = 0;
}
}
}
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (sender is DataGridViewComboBoxEditingControl comboBox && dataGridView1.CurrentCell.ColumnIndex == 0)
{
if (canDraw(e.Index))
{
Brush foregroundBrush = Brushes.Black;
e.DrawBackground();
e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), e.Font, foregroundBrush, e.Bounds, StringFormat.GenericDefault);
e.DrawFocusRectangle();
}
}
}
private bool canDraw(int index)
{
return index > -1 && index % 2 == 0;
}
}
Second, I can see the wanted result when I interact with the first column.
For example:
But the problem starts when I'm interacting with the second column which should display all the items:
I believe that reason for this problem is having the MeasureItem & DrawItem callback methods being invoked when the user is using the second combo box column.
My question is: How can I apply the logic above only for the first combo box column while keeping the original implementation for the second combo box column intact?
Thank you.
Upvotes: 0
Views: 163