Pasting content to new rows on the WPF DataGrid

On a previous post I talked about how to implement Clipboard.Paste for the DataGrid. The functionality was such that you could only paste to existing rows and cells. I got a customer request on how to paste to new rows so I thought I’d capture it here.

If you want to be able to paste to new rows, you just need to call IEditableCollectionView.AddNew before pasting to that row and optionally update selection. Here is the updated OnExecutePaste code to the previous sample,

protected virtual void OnExecutedPaste(ExecutedRoutedEventArgs args)

{

  // parse the clipboard data

  List<string[]> rowData = ClipboardHelper.ParseClipboardData();

  bool hasAddedNewRow = false;

  // call OnPastingCellClipboardContent for each cell

  int minRowIndex = Items.IndexOf(CurrentItem);

  int maxRowIndex = Items.Count - 1;

  int minColumnDisplayIndex = (SelectionUnit != DataGridSelectionUnit.FullRow) ? Columns.IndexOf(CurrentColumn) : 0;

  int maxColumnDisplayIndex = Columns.Count - 1;

  int rowDataIndex = 0;

  for (int i = minRowIndex; i <= maxRowIndex && rowDataIndex < rowData.Count; i++, rowDataIndex++)

  {

    if (CanUserPasteToNewRows && CanUserAddRows && i == maxRowIndex)

    {

        // add a new row to be pasted to

        ICollectionView cv = CollectionViewSource.GetDefaultView(Items);

        IEditableCollectionView iecv = cv as IEditableCollectionView;

        if (iecv != null)

        {

          hasAddedNewRow = true;

          iecv.AddNew();

          if (rowDataIndex + 1 < rowData.Count)

          {

           // still has more items to paste, update the maxRowIndex

           maxRowIndex = Items.Count - 1;
}
}

    }

    else if (i == maxRowIndex)

    {

          continue;
}

 

    int columnDataIndex = 0;

    for (int j = minColumnDisplayIndex; j < maxColumnDisplayIndex && columnDataIndex < rowData[rowDataIndex].Length; j++, columnDataIndex++)

    {

      DataGridColumn column = ColumnFromDisplayIndex(j);

      column.OnPastingCellClipboardContent(Items[i], rowData[rowDataIndex][columnDataIndex]);

    }

  }

  // update selection

  if (hasAddedNewRow)

  {
  UnselectAll();

    UnselectAllCells();

    CurrentItem = Items[minRowIndex];

    if (SelectionUnit == DataGridSelectionUnit.FullRow)

    {

      SelectedItem = Items[minRowIndex];

    }

    else if (SelectionUnit == DataGridSelectionUnit.CellOrRowHeader || SelectionUnit == DataGridSelectionUnit.Cell)

    {
SelectedCells.Add(new DataGridCellInfo(Items[minRowIndex], Columns[minColumnDisplayIndex]));
}
}

}

 

So with this new logic you can paste a set of rows starting at the NewItemPlaceholder and it will create a set of new rows where all the content will be pasted. For the selection logic, I just made it pretty basic and didn’t really enforce any specific requirements. Other than that, I just added one DP, CanUserPasteToNewRows, just to turn it on and off for this example. Here is the updated solution.

 

DataGrid_V1_ClipboardPaste_Sample2.zip