我有一个带有一些DataGridViewComboBoxColumns的DataGridView.DataGridView上有一个CellEnter事件处理程序,用于单击下拉组合框.
该列绑定到KeyValuePairs列表,ValueMember为"Key",DisplayMember为"Value".
当我点击组合框列时,它工作正常.但是,如果单元格处于"下拉"状态并且我单击另一个组合框(相同的列,不同的行),它会正确地取消选择旧单元格,选择并下拉新单元格,但是顶部的选定值会更改为在更改回正确的值之前,从旧单元格中获取值一瞬间.
例如,假设列表是A,B,C.在row1中,选择A,在row2中选择B. 我单击row1中的单元格,一切都是应该的.然后,当这个单元格下拉时,我点击第2行中的单元格.它正确地下降,但顶部的选定值变为A,然后立即切换回B(正确的值).
如果在单击第二个组合框单元格之前单击其他列中的单元格,则不会发生这种情况.
有没有办法防止这种情况发生?
重现问题的示例代码(事件处理程序连接到明显的事件):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PDGV
{
public partial class Form1 : Form
{
List<KeyValuePair<string, string>> bindingList = new List<KeyValuePair<string, string>>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Rows.Add(10);
bindingList.Add(new KeyValuePair<string,string>("aaa", "111"));
bindingList.Add(new KeyValuePair<string,string>("bbb", "222"));
bindingList.Add(new KeyValuePair<string,string>("ccc", "333"));
bindingList.Add(new KeyValuePair<string,string>("ddd", "444"));
bindingList.Add(new KeyValuePair<string,string>("eee", "555"));
BindComboList(2, bindingList);
}
private void BindComboList(int columnIndex, object list)
{
var column = dataGridView1.Columns[columnIndex] as DataGridViewComboBoxColumn;
if (column != null)
{
column.DataSource = new BindingSource(list, null);
column.DisplayMember = "Value";
column.ValueMember = "Key";
}
}
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
return;
dataGridView1.BeginEdit(true);
var control = dataGridView1.EditingControl as DataGridViewComboBoxEditingControl;
if (control != null)
control.DroppedDown = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
原因:
在DataGridViewEndEdit方法的最深处,它存储以前使用的EditingControl的副本。this.latestEditingControl = this.editingControl; 然后,当您开始编辑另一个单元格时,它将插入BeginEditInternal。在此过程中,它检查LatestEditingControl是否不为null且编辑类型是否与最后一个单元格相同,如果是,它将重用该控件,这就是您看到Flash的原因,它实际上是同一控件。
解决方案:
将latestEditingControl设置为null,则无法通过常规属性/方法访问此控件,必须使用反射。注意:这会导致完全不同的烦恼,现在您要离开的单元格会闪烁白色:),但确实可以解决您寻求帮助的特定问题。
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
return;
//this.latestEditingControl
Type t = dataGridView1.GetType();
FieldInfo viewSetter = t.GetField("latestEditingControl", BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance);
viewSetter.SetValue(dataGridView1, null);
}
Run Code Online (Sandbox Code Playgroud)