DataGridViewComboBoxColumn - 值滞后一瞬间

时间:2012-07-13 07:18:16

标签: c# datagridview

我有一个带有一些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;
        }
    }
}

3 个答案:

答案 0 :(得分:4)

The Cuase:

DataGridView的EndEdit方法深处,它存储了以前使用过的EditingControl this.latestEditingControl = this.editingControl;的副本。然后,当您开始编辑另一个单元格时,它会在BeginEditInternal中启动。在此过程中,它会检查latestEditingControl是否为空并且编辑类型与最后一个单元格相同,如果是,它会重新使用该控件,这就是为什么你看到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);
    }

答案 1 :(得分:2)

我没有像所描述的那样100%重复问题(我从未看到过延迟),但尝试取消订阅CellEnter事件并尝试将代码更改为此(来自How do I get DataGridView comboboxes to display their drop down list in one click?

public Form1() {
  InitializeComponent();

  dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
  dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
}

void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (e.Control is ComboBox) {
    SendKeys.Send("{F4}");
  }
}

当用户进入单元格时,应该弹出ComboBox。


或来自此解决方案Open dropdown(in a datagrid view) items on a single click

void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (e.Control is ComboBox) {
    ComboBox ctl = e.Control as ComboBox;
    ctl.Enter -= new EventHandler(ctl_Enter);
    ctl.Enter += new EventHandler(ctl_Enter);
  }
}

void ctl_Enter(object sender, EventArgs e) {
  (sender as ComboBox).DroppedDown = true;
}

答案 2 :(得分:1)

我假设它与windows 7的3d风格组合框(也许是vista,我还没有检查)

如果你

,我从未见过这种情况
comboboxcolumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;

但你可能不喜欢它的外观。您可以使用

隐藏丑陋的平面向下箭头
comboboxcolumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;

就像其他人说的那样,每列只有一个组合框控件('编辑控件'),同一个组合框显示在该列的当前活动单元格中。当未选择单元格时,它最多可以使用列类的绘制方法来绘制伪组合框以供用户查看。因此,当你将一个值推送到一个不可见的组合框然后在一个不同的地方重绘它时会发生某种特定的3d弹出式问题,这可能是某种内部的combox绘图问题。

尝试切换到'经典'窗口主题。然后组合框应该表现得很好。如果您可以强制组合框在Aero中渲染其在经典主题下的表现,那将会很有趣。我不确定它是否可能,但你可能想要研究它。

但无论如何,dgv与其他组合框样式没有这个问题这一事实让我觉得它只是新的组合框样式与数据网格视图不相称。