通过在单元格中键入将项目动态添加到DataGridView ComboBox列 [英] Dynamically add item to DataGridView ComboBox Column by typing in the cell

查看:89
本文介绍了通过在单元格中键入将项目动态添加到DataGridView ComboBox列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 DataGridView ,其中有一个 ComboBox 列,当下拉列表时,我必须更新每个ComboBox的可能值节目。我还必须使 ComboBox es能够具有自定义类型的值。键入新值时,应将其添加到可能值列表中。问题是我得到无限多个 DataError 事件触发器(错误消息框),我知道如何通过仅更改 DataGridViewDataErrorEventArgs中的字段来处理它对象,但我知道这不是正确的处理方式:

I have a DataGridView that has a ComboBox column and I must update each ComboBox's possible values when its drop down shows. I also must make the ComboBoxes capable of having custom typed values. When a new value is typed, it should be added to the list of possible values. The problem is that I get infinitely many DataError event triggers (error message boxes), I know how to handle it by just changing a field in the DataGridViewDataErrorEventArgs object, but I know it is not the correct way to handle it:

private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
    e.Cancel = false;
}

如果我以错误的方式操作,请从下拉列表中选择一个值向下或输入新值时,会触发 CellValueChanged ,但关闭的 ComboBox 不会显示当前值,但已经显示现有值(列表中的第一个)。

If I do it in the incorrect way, after selecting a value from the drop down or typing a new value, the CellValueChanged is triggered but the closed ComboBox does not display the current value but an already existing value (the first in the list).

在以下代码中,Form子类为 Form2 ,值存储在 str 字段中,并调用 UpdatePossibleValues 方法来更新所有<$ c中的可能值$ c> ComboBox 位于数据网格视图的唯一列中,即 DataGridViewComboBoxColumn

In the following code the Form subclass is Form2, the initial values are stored in the str field and the UpdatePossibleValues method is called to update the possible values in all the ComboBoxes inside the only column in the data grid view, a DataGridViewComboBoxColumn:

public Form2()
{
    InitializeComponent();

    dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;

    UpdatePossibleValues();
}

internal List<string> str = new List<string>()
{
    "val1",
    "val2"
};

private void DataGridView1_EditingControlShowing(object sender, 
    DataGridViewEditingControlShowingEventArgs e)
{
    if (dataGridView1.CurrentCell == null ||
        dataGridView1.CurrentCell.OwningColumn == null ||
        dataGridView1.CurrentCell.OwningColumn.Name != "column1")
    {
        return;
    }
    var combo = e.Control as DataGridViewComboBoxEditingControl;
    if (combo == null)
    {
        return;
    }

    var cb = combo as ComboBox;
    UpdatePossibleValues(cb);
    cb.DropDownStyle = ComboBoxStyle.DropDown; // this makes the ComboBoxes editable
    cb.Validating += Cb_Validating;
}

private void Cb_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
    var cbo = sender as ComboBox;
    string t = cbo.Text;

    var cell = (DataGridViewComboBoxCell)dataGridView1.CurrentCell;

    // add the value to the list if it is not there
    if (!string.IsNullOrEmpty(t) &&
        !cbo.Items.Contains(t))
    {
        str.Add(t);

        UpdatePossibleValues(cbo);

        cell.Value = t;

        e.Cancel = false;
    }
}

private void UpdatePossibleValues(ComboBox cb = null)
{
    if (cb == null)
    {
        var col = dataGridView1.Columns[0] as DataGridViewComboBoxColumn;

        col.Items.Clear();
        foreach (string s in str)
        {
            col.Items.Add(s);
        }
    }
    else
    {
        cb.Items.Clear();
        foreach (string s in str)
        {
            cb.Items.Add(s);
        }
    }
}

截屏:

推荐答案

要将项目动态添加到 DataGridViewComboBoxColumn


  1. Hanlde EditingControlShowing 并获得 DataGridViewComboBoxEditingControl

  2. 将编辑控件 DropDownStyle 设置为 DropDown

  3. 句柄正在验证编辑控件事件,并确保仅将事件处理程序附加一次。

  4. 检查文本是否的编辑控件在以下项目中不存在:


    • 将其添加到th的数据源e列

    • 然后通过将列的数据源设置为null并再次分配数据源来重置该列的数据源。

  1. Hanlde EditingControlShowing and get the DataGridViewComboBoxEditingControl
  2. Set editing control DropDownStyle to DropDown
  3. Handle Validating event of editing control and make sure you attach the event handler just once.
  4. Check if the Text of the editing control doesn't exists in the items:
    • Add it to data source of the column
    • Then reset data source of the column by setting it to null and assigning data source again.

注意:


  • 如果您有多个组合框,确保对组合框使用不同的数据源,并在验证事件中更新相应的数据源。

  • If you have multiple combo box, make sure you use different data sources for combo boxes and update corresponding data source in validating event.

如果使用匿名方法处理事件,请确保关于捕获变量的正确假设。为简单起见,您可以使用常规方法处理事件。

If you handle the events using anonymous method, make sure you have a correct assumption about captured variables. To make it simple, you can handle the event using a normal method.

示例

下面的示例显示 DataGridView 具有两个 DataGridViewComboBoxColumn 对于第二个示例,可以在运行时在组合框中键入新值。

The following example shows a DataGridView having two DataGridViewComboBoxColumn which for the second one, you can add new values by typing in the combo box at run-time.

要运行该示例,请创建一个窗体并将 DataGridView 放到新窗体上,然后将以下代码复制并粘贴到该窗体中:

To run the example, create a Form and drop a DataGridView on a new Form and just copy and paste the following code in the form:

private List<String> comboSource1;
private List<String> comboSource2;
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    comboSource1 = new List<string> { "A", "B" };
    comboSource2 = new List<string> { "1", "2" };

    var dt = new DataTable();
    dt.Columns.Add("C1");
    dt.Columns.Add("C2");
    dt.Rows.Add("A", "1");
    dt.Rows.Add("B", "2");

    var c1 = new DataGridViewComboBoxColumn();
    c1.Name = "C1";
    c1.DataPropertyName = "C1";
    c1.DataSource = comboSource1;

    var c2 = new DataGridViewComboBoxColumn();
    c2.Name = "C2";
    c2.DataPropertyName = "C2";
    c2.DataSource = comboSource2;

    dataGridView1.Columns.AddRange(c1, c2);

    this.dataGridView1.DataSource = dt;
    dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
    dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
}





private void dataGridView1_EditingControlShowing(object sender,
    DataGridViewEditingControlShowingEventArgs e)
{
    var dataGridView = sender as DataGridView;
    if (dataGridView?.CurrentCell?.ColumnIndex != 1) return;
    var comboBox = e.Control as DataGridViewComboBoxEditingControl;

    if (comboBox == null) return;
    comboBox.DropDownStyle = ComboBoxStyle.DropDown;
    if (!true.Equals(comboBox.Tag))
    {
        comboBox.Tag = true;
        comboBox.Validating += (obj, args) =>
        {
            var column = (DataGridViewComboBoxColumn)dataGridView.CurrentCell.OwningColumn;
            var list = comboBox.DataSource as List<string>;
            if (list == null) return;
            var txt = comboBox.Text;
            if (!list.Contains(txt))
            {
                list.Add(txt);
                column.DataSource = null;
                column.DataSource = list;
            }
            dataGridView.CurrentCell.Value = txt;
            dataGridView.NotifyCurrentCellDirty(true);
        };
    }
}

这篇关于通过在单元格中键入将项目动态添加到DataGridView ComboBox列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆