为什么在以编程方式添加新项目后 WPF DataGridCell.Content 是 TextBlock 而不是 TextBox?

Why is a WPF DataGridCell.Content a TextBlock instead of a TextBox after adding a new item programmatically?

我想将 Excel table 中的数据复制粘贴到 WPF DataGrid 中。为此,我有以下函数,它在 KeyDown 事件中被调用:

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<string> rowDataCombined = pastedData.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
    List<string[]> rowData = new List<string[]>();
    foreach (var row in rowDataCombined)
    {
        rowData.Add(row.Split(new string[] { "\t" }, 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 < maxRowIdx; r++)
    {
        if(r > 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 < maxColIdx; c++)
        {
            var presenter = FindVisualChild<DataGridCellsPresenter>(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;
                }
            }
        }
    }
}

注意行 if(cell.Content is TextBox tb):

DataGrid 已将 AutoGenerateColumns 设置为 true。生成的单元格最初似乎获得 TextBlock 作为内容,后来更改为 TextBox。问题是,是什么触发了这个变化,我可以手动完成吗?如果我只是将内容更改为 TextBox 以防它是 TextBlock,我会破坏任何东西吗?

经过一段时间的搜索,我想我找到了问题所在。默认情况下,我已将 属性 DataGrid.CanUserAddRows 设置为 true。在编辑最后一行之后,似乎 DataGrid 在程序化编辑之后添加了一个由 TextBlocks 组成的空行(直到用户在 GUI 中开始编辑)。

在我的粘贴函数开始时将标志设置为 false 并在返回前设置为 true 修复了问题。