I'm using C# WinForms .NET 4.7.2. I'm encountering what appears to be a bug when using DataGridViewComboBoxColumns in a DataGridView. When I enter data into it with auto-append (where the first-character of data-entry is all that's required), I see the correct drop-down item appear. If I quickly tab to the next cell, sometimes the entered value disappears from the ComboBox cell. This only happens when I enter and leave the column quickly (tabbing along as most data-entry personnel would). This bug forces the data-entry person to go back to the blank column and try again. If they're too fast again, it can stay blank again. I've tested a number of scenarios and events and cannot pin down what's causing this, as setting break points in (e.g.) the CurrentCellDirtyStateChanged event causes the bug to no longer appear. It certainly seems speed-related, as I cannot reproduce the behaviour when I'm tabbing through more slowly.
It would be great if it wasn't a bug and you could tell me what I'm doing wrong to cause this behaviour. Otherwise, if it is a bug, work-around ideas that forces the value to stick would be great.
I'm able to reproduce the bug with the following new project. The bug is a little more pronounced in my real project, so I suppose the bug may get worse with scale. Strange that I haven't encountered this before, as this isn't my first time using ComboBoxColumns in a DataGridView.
How to recreate:
- Create a new C# WinForms project in VS (I'm using MS VS Pro 2019 RC V 16)
- Add a
DataGridViewto the form and fully dock it - Code for the form:
using System;
using System.Data;
using System.Windows.Forms;
namespace TestingStuff
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
DataTable dtString1;
DataTable dtString2;
DataTable dtString3;
private void Form1_Load(object sender, EventArgs e)
{
// create three combobox columns and put them side-by-side:
// first column:
DataGridViewComboBoxColumn dgvcbc1 = new DataGridViewComboBoxColumn();
dgvcbc1.DataPropertyName = "String1";
dgvcbc1.Name = "String1";
dtString1 = new DataTable("String1Options");
dtString1.Columns.Add("String1Long", typeof(string));
dtString1.Rows.Add("apple");
dtString1.Rows.Add("bob");
dtString1.Rows.Add("clobber");
dtString1.Rows.Add("dilbert");
dtString1.Rows.Add("ether");
dgv.Columns.Insert(0, dgvcbc1);
dgvcbc1.DisplayMember = dtString1.Columns[0].ColumnName;
dgvcbc1.ValueMember = dtString1.Columns[0].ColumnName;
dgvcbc1.DataSource = dtString1;
dgvcbc1.FlatStyle = FlatStyle.Flat;
// create the second column:
DataGridViewComboBoxColumn dgvcbc2 = new DataGridViewComboBoxColumn();
dgvcbc2.DataPropertyName = "String2";
dgvcbc2.Name = "String2";
dtString2 = new DataTable("String2Options");
dtString2.Columns.Add("String2Long", typeof(string));
dtString2.Rows.Add("apple");
dtString2.Rows.Add("bob");
dtString2.Rows.Add("clobber");
dtString2.Rows.Add("dilbert");
dtString2.Rows.Add("ether");
dgv.Columns.Insert(1, dgvcbc2);
dgvcbc2.DisplayMember = dtString2.Columns[0].ColumnName;
dgvcbc2.ValueMember = dtString2.Columns[0].ColumnName;
dgvcbc2.DataSource = dtString2;
dgvcbc2.FlatStyle = FlatStyle.Flat;
// create the third column:
DataGridViewComboBoxColumn dgvcbc3 = new DataGridViewComboBoxColumn();
dgvcbc3.DataPropertyName = "String3";
dgvcbc3.Name = "String3";
dtString3 = new DataTable("String3Options");
dtString3.Columns.Add("String3Long", typeof(string));
dtString3.Rows.Add("apple");
dtString3.Rows.Add("bob");
dtString3.Rows.Add("clobber");
dtString3.Rows.Add("dilbert");
dtString3.Rows.Add("ether");
dgv.Columns.Insert(2, dgvcbc3);
dgvcbc3.DisplayMember = dtString3.Columns[0].ColumnName;
dgvcbc3.ValueMember = dtString3.Columns[0].ColumnName;
dgvcbc3.DataSource = dtString3;
dgvcbc3.FlatStyle = FlatStyle.Flat;
}
}
}
- Run it
- Enter your data quickly (using autocomplete and
[Tab]key efficiently) - Notice that your
DataGridViewComboBoxColumnvalues sometimes disappear immediately after leaving the cell
Edit: In addition, I've noticed that this bug only occurs on cells that are currently blank - the bug cannot be reproduced when editing a cell from one value to another.
Thanks for any insight.
I found the bug easy to reproduce with your latest code, manually entering [a] [Tab] [b] [Tab] [c] [Tab] either slow (works) or fast (fails). I also added A-B-C and C-D-E buttons to send key events very rapidly to test in a repeatable way. Below the proposed solution is a debug trace I performed to see what's going on. What I found curious is that the
DataGridViewComboBoxEditingControlalways gains focus with its Text value equal to "apple". I decided to try setting the first value for theColumn.DataSourcetoString.Emptyinstead.You may have seen that I had already found various ways to make a work-around that forces the value to stick. But I'm changing my answer because this looks like a real honest solution.
PROPOSED SOLUTION - ADD THESE THREE LINES TO THE LOAD CODE
My theory as to why this would be an effective fix: The empty entry guarantees that any non-empty match in the auto-append list will register as a 'change'. See if you can repro. I get 0 failures on this version with either manual entry or button clicks.
DEBUGGING AND TESTING INFORMATION FOLLOWS
I placed
Debug.WriteLine()on various events to see what's going on.NORMAL (slow)
PATHOLOGICAL (fast)
AUTOMATED TESTING UPDATE (from the "having too much fun" department)
It bothered me that there was so much variable with this manual testing interval. If we're ever to get to the bottom this, there has to be a way to send the keystrokes rapidly in an automated way.
Thanks for the brain teaser regardless of outcomes it's been a blast. Cheers.