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:
Custom sorting, column selection, single-click editing
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.aspxAnonymous
September 19, 2008
As you might have heard, .NET Framework 3.5 SP1 and Visual Studio 2008 SP1 are out today! There are aAnonymous
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. MerciAnonymous
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 removedAnonymous
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 functionalityAnonymous
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, sachinAnonymous
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