title: Dynamically add item to DataGridView ComboBox Column by typing in the cell
body: <p>I have a <code>DataGridView</code> that has a <code>ComboBox</code> column and I must update each ComboBox's possible values when its drop down shows. I also must make the <code>ComboBox</code>es 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 <code>DataError</code> event triggers (error message boxes), I know how to handle it by just changing a field in the <code>DataGridViewDataErrorEventArgs</code> object, but I know it is not the correct way to handle it:</p>
  
  <pre><code>private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
  {
      e.Cancel = false;
  }
  </code></pre>
  
  <p>If I do it in the incorrect way, after selecting a value from the drop down or typing a new value, the <code>CellValueChanged</code> is triggered but the closed <code>ComboBox</code> does not display the current value but an already existing value (the first in the list).</p>
  
  <p>In the following code the Form subclass is <code>Form2</code>, the initial values are stored in the <code>str</code> field and the <code>UpdatePossibleValues</code> method is called to update the possible values in all the <code>ComboBox</code>es inside the only column in the data grid view, a <code>DataGridViewComboBoxColumn</code>:</p>
  
  <pre><code>public Form2()
  {
      InitializeComponent();
  
      dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
  
      UpdatePossibleValues();
  }
  
  internal List&lt;string&gt; str = new List&lt;string&gt;()
  {
      "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) &amp;&amp;
          !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);
          }
      }
  }
  </code></pre>
  
  <p>Screenshots:</p>
  
  <p><a href="https://i.stack.imgur.com/XSc06.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XSc06.png" alt="normal use"></a></p>
  
  <p><a href="https://i.stack.imgur.com/ayg5q.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ayg5q.png" alt="data error"></a></p>