Condividi tramite


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

  • Anonymous
    September 19, 2008
    PingBack from http://blogs.msdn.com/vinsibal/archive/2008/09/16/wpf-datagrid-styling-rows-and-columns-based-on-header-conditions-and-other-properties.aspx

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

  • Anonymous
    September 19, 2008
    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

  • Anonymous
    September 20, 2008
    de Boucaud, I added a translator at the top of the page.  Hope that helps.

  • Anonymous
    September 20, 2008
    The comment has been removed

  • Anonymous
    September 22, 2008
    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.

  • Anonymous
    September 25, 2008
    On a previous post I talked about how to implement Clipboard.Paste for the DataGrid. The functionality

  • Anonymous
    March 04, 2009
    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?

  • Anonymous
    October 20, 2009
    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.

  • Anonymous
    October 22, 2009
    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

  • Anonymous
    October 23, 2009
    Great article. How can i get context menu to show up? I would like to right click and paste.

  • Anonymous
    October 30, 2009
    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