title: Why is a WPF DataGridCell.Content a TextBlock instead of a TextBox after adding a new item programmatically?
body: <p>I want to copy-paste data from a Excel table into a WPF <code>DataGrid</code>. For this I have the following function, which gets called on the <code>KeyDown</code> event:</p>
  <pre><code>private void OnDataGridPasteData(object sender, KeyEventArgs e)
  {
      if ((Keyboard.Modifiers != ModifierKeys.Control) || e.Key != Key.V)
          return;
  
      DataGrid dg = (DataGrid)sender;
  
      var pastedData = Clipboard.GetText();
      List&lt;string&gt; rowDataCombined = pastedData.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
      List&lt;string[]&gt; rowData = new List&lt;string[]&gt;();
      foreach (var row in rowDataCombined)
      {
          rowData.Add(row.Split(new string[] { &quot;\t&quot; }, StringSplitOptions.None));
      }
  
      int initialRowIdx = Math.Max(dg.Items.IndexOf(dg.SelectedItem), 0);
      int initialColIdx = dg.CurrentCell.Column.DisplayIndex;
      int maxColIdx = dg.Columns.Count;
      int maxRowIdx = initialRowIdx + rowData.Count;
  
      Type sourceType = dg.ItemsSource.GetType().GetGenericArguments()[0];
      var sourceList = (IList)dg.ItemsSource;
  
      for (int r = initialRowIdx; r &lt; maxRowIdx; r++)
      {
          if(r &gt; dg.Items.Count - 1)
          {
              var newRowObject = Activator.CreateInstance(sourceType);
              sourceList.Add(newRowObject);
          }
  
          DataGridRow dgRow = GetRowFromDataGrid(dg, r);
          if (dgRow == null)
              continue;
  
          for (int c = initialColIdx; c &lt; maxColIdx; c++)
          {
              var presenter = FindVisualChild&lt;DataGridCellsPresenter&gt;(dgRow);
              // try to get the cell but it may possibly be virtualized
              var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(c);
              if (cell == null)
              {
                  // now try to bring into view and retreive the cell
                  dg.ScrollIntoView(dgRow, dg.Columns[c]);
                  cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(c);
              }
  
              if(cell != null)
              {
                  cell.Focus();
                  if (!dg.BeginEdit()) //abort pasting if editing fails
                  {
                      dg.CancelEdit();
                      return;
                  }
  
                  if(cell.Content is TextBox tb)
                  {
                      tb.Text = rowData[r - initialRowIdx][c - initialColIdx];
                  }
                  if(!dg.CommitEdit()) // abort pasting if commit fails (e.g. wrong entry type)
                  {
                      dg.CancelEdit();
                      return;
                  }
              }
          }
      }
  }
  </code></pre>
  <p>Notice the line <code>if(cell.Content is TextBox tb)</code>:</p>
  <ul>
  <li>For existing <code>DataGridCells</code> this will be <code>true</code></li>
  <li>For newly added items (line <code>sourceList.Add(newRowObject);</code>) this will be false. The content type then is a <code>TextBlock</code></li>
  <li>If I add all the needed rows in a <code>while</code> loop in the same manner as above before entering the <code>for</code> loops, it will also result to <code>true</code>. However, I want to abort the whole operation, if the pasting fails without having the extra rows afterwards.</li>
  </ul>
  <p>The <code>DataGrid</code> has <code>AutoGenerateColumns</code> set to <code>true</code>. Generated cells seem to get a <code>TextBlock</code> initially as content, which is later changed to a <code>TextBox</code>. Question is, what triggers this change, and can I do it manually? Would I break anything, if I simply change the content to a <code>TextBox</code> in case it is a <code>TextBlock</code>?</p>