Click here to Skip to main content
15,071,430 members
Articles / Desktop Programming / WPF
Posted 26 Aug 2011


20 bookmarked

Implementing Copy and Paste for a WPF DataGrid in .NET 4

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
31 Aug 2011CPOL4 min read
Using the DataZGrid provided by .NET 4, this article shows how to copy and paste between cells.


Update - See restriction 3 below.

Using the standard DataGrid that was added with .NET 4, I found that I needed to implement copy and paste. Searching the internet came up with solutions that either worked with Silverlight or with some sort of pre-release version that you could add to Visual Studio 2008 (.NET 3).

To my horror, I had to actually figure something out and write some code. I'm very new to WPF and have spent the last few months copying example code off the internet and modifying it for my use but I think I have finally written something that might be of use to other people, so here it is.

Credit goes to the following two pages that helped, and some code was taken from the second one (credited in comments):

The solution allows you to do some limited copy and pasting between cells. In the example, I have a table of people with fields first name, second name, and legs (a number - usually 2). In the application I was working on, it made no sense to copy from one column to another. So in this example, you can't copy the legs column to the first name column (for example). This is intentional and the restriction could be removed easily by deleting some checks.

Restrictions / problems to solve!

  1. It only deals with strings or integers. It should be easy to expand on the types allowed with more code but perhaps that can be avoided completely with a different implementation.
  2. The clipboard is only converted from one particular format. I need to see if copying from Excel works - otherwise I probably need to put some code back into DatagridHelper that I removed!
  3. Important If the rows are re-ordered, it breaks this code! For this reason, I suggest you don't use this code.

Reto Ravisio saw this article and provided a much better solution. I have taken that, changed it slightly, and provided a complete solution file that uses his code:

Hopefully this will help beginners like myself use that code.

Using the code

I will go over some of the code you have to copy into your project, but you'll have to see the entire solution to get all the required code. This is a tester to show you the main principles so you can decide if it's for you.

The DataGrid is declared like this:

<DataGrid Name="dataGrid1" ItemsSource="{Binding PeopleList}" 

Note that the SelectionUnit is set to Cell. This allows individual cells to be selected rather than the whole row. The items are taken from an ObserverableCollection and the columns are automatically generated.

The KeyDown event is set to detect the paste operation:

void dataGrid1_KeyDown(object sender, KeyEventArgs e)
  if (e.Key == Key.V &&
      (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
    if (ValidatePaste() == false)

         Clipboard.GetData(DataFormats.Text) as string);

As you can see, a View Model is used.

The View Model Paste function uses the ClipboardHelper class (taken from the MSDN blog mentioned in the introduction) to convert the string version of the copied cells into a list of string arrays representing the cells on each row. Then it loops through the target rows setting the ObservableCollection.

Reflection is used to set the properties in the collection having only a string representing the property name. This avoids having a switch statement checking the display index value and matching that up to a property. It would have made the code very tedious to write and not easily re-usable.

The SetProperty function implements that functionality:

private void SetProperty(Person person, string propertyName, string cellItem)
  // Use reflection to set the property to the value
  Type type = person.GetType();
  PropertyInfo prop = type.GetProperty(propertyName);
  if (prop == null)
    Debug.WriteLine("Property not found: " + propertyName);
  if (prop.PropertyType == typeof(string)) // only caters for string or integer types
    prop.SetValue(person, cellItem, null);
    prop.SetValue(person, int.Parse(cellItem), null);

You can see in the code above where the restriction on having only strings or integers comes from.

The People class is a simple container class that implements INotifyPropertyChanged:

class Person : INotifyPropertyChanged
    public Person(string first, string second)
      FirstName = first;
      SecondName = second;
      Legs = 2;
    public string FirstName { set; get; }
    public string SecondName { set; get; }
    public int Legs { set; get; }

#region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));


The code which populates the map of property names and display indexes (used in the VM Paste function) relies on this bit of code in the code-behind:

private void dataGrid1_ColumnReordered(object sender, DataGridColumnEventArgs e)
    foreach (DataGridColumn col in dataGrid1.Columns)
        viewModel.AddColumnMapping(col.DisplayIndex, col.SortMemberPath);

I'm assuming that the SortMemberPath will always be the same as the property name in the People class. It was in my case.


  • 2011-09-01: A new version which gets the column information when the columns are re-ordered rather than when loaded. Updated a downloadable complete solution based on Reto's article.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

United Kingdom United Kingdom
No Biography provided

Comments and Discussions

QuestionBest Way? Pin
Reto Ravasio28-Aug-11 1:04
MemberReto Ravasio28-Aug-11 1:04 
I'm wondering whether the solution you present here is the best way to accomplish this.
By getting the data out of the clipboard, you get it in exactly the order as layed out on the screen. Then you copy that data into the model without regard of column and and row ordering/visibility. You can easly see the effect it has when you move around the columns.
Another disadvantage is that you need to have an implementation of a converter for each type of data you have in the grid. (see implementation in SetProperty::SetProperty) even tough the binding engine already knows how to convert from a string to the required type (at least for all writeable columns).

By copying the data into the grid instead of the model one could prevent all kinds of problems. But then I didn't find anything on the internet that followed that route so it maybe just impossible to do it.
AnswerRe: Best Way? Pin
Peter_Smithson28-Aug-11 21:30
MemberPeter_Smithson28-Aug-11 21:30 
GeneralRe: Best Way? Pin
Reto Ravasio29-Aug-11 7:44
MemberReto Ravasio29-Aug-11 7:44 
GeneralRe: Best Way? Pin
Peter_Smithson30-Aug-11 21:24
MemberPeter_Smithson30-Aug-11 21:24 
GeneralRe: Best Way? Pin
Peter_Smithson30-Aug-11 23:11
MemberPeter_Smithson30-Aug-11 23:11 
GeneralRe: Best Way? Pin
Reto Ravasio31-Aug-11 12:44
MemberReto Ravasio31-Aug-11 12:44 
GeneralRe: Best Way? Pin
Peter_Smithson31-Aug-11 22:13
MemberPeter_Smithson31-Aug-11 22:13 
GeneralRe: Best Way? Pin
Reto Ravasio1-Sep-11 10:14
MemberReto Ravasio1-Sep-11 10:14 
GeneralRe: Best Way? Pin
Peter_Smithson5-Sep-11 5:54
MemberPeter_Smithson5-Sep-11 5:54 
AnswerRe: Best Way? Pin
Member 85358323-Jan-12 2:43
MemberMember 85358323-Jan-12 2:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.