WPF DataGrid – Clipboard Paste Sample


In the v1 release (and CTP) of the WPF DataGrid there will be support for Clipboard.Copy but no support out of the box for Clipboard.Paste.  However, there is extensibility support for Clipboard.Paste which I will show how to implement in this post.


In DataGridColumn.cs an additional API, OnPastingCellClipboardContent, exists so you can add pasting functionality to each DataGridCell.  A similar API, OnCopyingCellClipboardContent, also exists and behaves the same way except it is used from copying content.  OnPastingCellClipboardContent has two parameters; item, which is the particular data item in the list of DataGrid.Items to update, and cellContent, which is the actual content to add to the cell itself.


So with that in mind, what I need to do is get the content currently on the clipboard, parse the data, and then call OnPastingCellClipboardContent for each cell.  I’m also going to setup a command that is similar to the Copy command and I’ve decided to subclass DataGrid.  Here is the code for creating the command:



public class CustomDataGrid : DataGrid


{


  static CustomDataGrid()


  {


      CommandManager.RegisterClassCommandBinding(


          typeof(CustomDataGrid),


          new CommandBinding(ApplicationCommands.Paste,


           new ExecutedRoutedEventHandler(OnExecutedPaste),


           new CanExecuteRoutedEventHandler(OnCanExecutePaste)));
  }


 


 


}


 


In the copy scenario, the OnCanExecuteCopy only fires if you have selected cells.  For the onCanExecutePaste scenario I want it to be such that you can paste content as long as any particular cell is selected.  So in my OnCanExecutePaste method, I only need the CurrentCell to not be null.



protected virtual void OnCanExecutePaste(CanExecuteRoutedEventArgs args)


{


  args.CanExecute = CurrentCell != null;


  args.Handled = true;


}


 


Before getting into OnExecutePaste, I want to talk just a little bit about the parsing stuff.  I created a simple parser for CSV and Text format.  The algorithms are pretty straightforward so I’m not going to show them here.  The parser should work when copying data from the WPF DataGrid as well as copying Excel data to the WPF DataGrid.  For Excel data I’m using the Text parser.  What the parser returns is a list of a list which basically represent the rows and cells of a DataGrid. 


So in my OnExecutePaste method, I am going to iterate through the set of cells starting at the CurrentCell.  It is possible that the set of content to be pasted is more than the set of cells to paste them in or visa-versa.  So I need to keep track of the max rows and columns that can be pasted to as well as the max data that can be placed in the cells.  Here is the code snippet:



protected virtual void OnExecutedPaste(ExecutedRoutedEventArgs args)


{       


  // parse the clipboard data


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


 


  // 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++)


  {


    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]);


    }


  }


}


 


I did make one condition when SelectionUnit is equal to FullRow.  For that scenario when users copy a full row and paste to another full row the column index should not matter as their intention is to paste the entire row to the new row.  So for that I set minColumnDisplayIndex to 0.


You can check out the full sample here.  For more information on clipboard paste see this post which is another sample.


Other DataGrid Samples:


ScrollViewer with ToolTip


Custom sorting, column selection, single-click editing


Tri-state sorting


Styling rows and columns based on header conditions


 


 

DataGrid_V1_ClipboardPaste_Sample.zip

Comments (12)

  1. As you might have heard, .NET Framework 3.5 SP1 and Visual Studio 2008 SP1 are out today! There are a

  2. de Boucaud says:

    Mettez en Français Silverlight sur votre site puisqu’il est en Anglais et que je n’y comprend rien du tout en Anglais donc en Français sa serait bien, et je ne suis pas le seul Français qui ne comprend pas l’Anglais.

    Merci

  3. vinsibal says:

    de Boucaud,

    I added a translator at the top of the page.  Hope that helps.

  4. rod mac says:

    Why is paste not available ‘out of the box’? Wasn’t that a feature in Visual Basic 3’s DataGrid? And why is it taking so long for VS2008 to aquire a WPF grid when WPF 3.0 was out for VS2005 in 2006?

  5. vinsibal says:

    rod mac,

    As it turns out, the implementation of Paste is more specific to the app. It was for some of the same reasons that Winforms DataGridView did not implement it either.

    For the DataGrid coming out at this stage, WPF is a brand new platform with a number of new capabilities we introduced first in 2006.  With any new platform and especially one as broad as WPF, there’s a lot of ground to cover with tools, controls, features.  It has taken us longer than we expected but we feel very good about the set of improvements we’ve made since V1 and we’re particularly pleased to be shipping very capable DataGrid.  We hope you find it meets your needs.

  6. On a previous post I talked about how to implement Clipboard.Paste for the DataGrid. The functionality

  7. Ron Larvick says:

    Any hints on how might impliment different types of pastes? For example, lets say the user copies one cell in Excel to paste to 10 cells in the WPF datagrid?

  8. PandaWood says:

    This is great thank you.

    I found it doesn’t cater for columns that have been dragged out of order (and starts pasting all over the place). If I do this, will post the code back.

  9. sachin says:

    I am using Toolkit datagrid and looking for built in (cut, copy, paste).

    I am using MVVM pattern and my cells are using CellTemplate when row is selected and in edit mode it uses CellEditingTemplate.

    I would like to get copy,paste keybord shortcuts and context menu.

    Any help would be greatly appreciated.

    Thanks,

    sachin

  10. sachin says:

    Great article. How can i get context menu to show up? I would like to right click and paste.

  11. sachin says:

    Ok. I am able to add context menu in your sample by creating windows resource context menu and setting it on defaultCellStyle.

    <Window.Resources>

       <ContextMenu x:Key="mnuContext">

    <MenuItem Header="Copy" Command="Copy"/>

    <MenuItem Header="Cut" Command="Cut"/>

    <MenuItem Header="Paste" Command="Paste"/>

       </ContextMenu>

    </Window.Resources>

    <Style x:Key="defaultCellStyle" TargetType="{x:Type dg:DataGridCell}">

     <Setter Property="ContextMenu" Value="{StaticResource mnuContext}" />

    and then set grid cell style as follows

    <local:CustomDataGrid

       CellStyle="{StaticResource defaultCellStyle}"  >

    Thought someone might find it helpful.

    Thanks,

    sachin