One of the common tasks that many end-users have is to copy data from an application to Excel or Word or any other Windows Apps. The way to do this is to copy items to the Clipboard and Microsoft provides a really nice class that makes this simple to do. The point of this article is to offer a brief glimpse on how to copy cell values from the XamDataGrid to the clipboard. It will focus on three different selection strategies range select (only for contiguous ranges), record selection (rows), or field selections (columns).
To enable selection in the above three scenarios you may also want to make some modifications to the XamDataGrid that allow for the user to easily select a range of cells and allow them to select all of the cells in a field by clicking on a field header. The code to do this looks like this:
<igDP:XamDataGrid.FieldSettings> <igDP:FieldSettings LabelClickAction="SelectField" CellClickAction="SelectCell" /> </igDP:XamDataGrid.FieldSettings>
To ensure that the XamDataGrid responds to Ctrl+C you need to add input bindings to the XamDataGrid that point to that particular keystroke. To do this you need to find a way to point the CTRL+C keystroke to an event or command that fires off the XamDataGrid. The code to handle this gesture looks like this:
<igDP:XamDataGrid.InputBindings> <KeyBinding Command="{x:Static myApp:Window1.CopyCommand}" Gesture="CTRL+C" /> </igDP:XamDataGrid.InputBindings>
In the procedural code you now need to define this copy command. To do so, you need to declare it:
public static RoutedCommand CopyCommand = new RoutedCommand();
I hooked up this command in the constructor for our Window:
public Window1() { CommandBinding copyCommandBinding = new CommandBinding(CopyCommand, ExecutedCopyCommand); this.CommandBindings.Add(copyCommandBinding); InitializeComponent(); }
After you have the command bindings set up you can handle the ExecutedCopyCommand and this is what will actually be called by the CTRL+C method. In this method, I look at the XamDataGrid that calls the command and check to see which of the SelectedItemsCollections hold items and call a method to handle them based on the actual selected collection:
private void ExecutedCopyCommand(object sender, ExecutedRoutedEventArgs e) { Infragistics.Windows.DataPresenter.XamDataGrid myGrid = e.Source as Infragistics.Windows.DataPresenter.XamDataGrid; if (myGrid.SelectedItems.Cells.Count > 0) CopySelectedCells(myGrid); else if (myGrid.SelectedItems.Records.Count > 0) CopySelectedRecords(myGrid); else if (myGrid.SelectedItems.Fields.Count > 0) CopySelectedFields(myGrid); }
This method will enable the end-user to select a range of cells and format them appropriately to copy their text to clipboard. This formatting also enables the copying to be direct to rows/columns in Excel. One caveat is that it only allows for a contiguous range of cells (as this is the only capabilities enabled by Excel):
private static void CopySelectedCells(Infragistics.Windows.DataPresenter.XamDataGrid myGrid) { string myInternalClipboard = null; int currentRecordLevel = 0; Infragistics.Windows.DataPresenter.SelectedCellCollection mySelectedCells = myGrid.SelectedItems.Cells; foreach (Cell myCell in mySelectedCells) { if (myInternalClipboard == null) { currentRecordLevel = myCell.Record.DataItemIndex; myInternalClipboard = myCell.Value.ToString(); } else if (myCell.Record.DataItemIndex == currentRecordLevel) myInternalClipboard = myInternalClipboard + "\t" + myCell.Value.ToString(); else { currentRecordLevel = myCell.Record.DataItemIndex; myInternalClipboard = myInternalClipboard + "\r\n" + myCell.Value.ToString(); } } myInternalClipboard = myInternalClipboard + "\r\n"; Clipboard.Clear(); Clipboard.SetText(myInternalClipboard); }
This method allows the end-user to select a record(row) or a range of rows and copy them to the clipboard and then past them to a particular app while still distinguishing different columns:
private static void CopySelectedRecords(Infragistics.Windows.DataPresenter.XamDataGrid myGrid) { string myInternalClipboard = null; bool IsNewRecord = true; Infragistics.Windows.DataPresenter.SelectedRecordCollection mySelectedRecords = myGrid.SelectedItems.Records; foreach (DataRecord myRecord in mySelectedRecords) { foreach(Cell myCell in myRecord.Cells) { if (myInternalClipboard == null || IsNewRecord == true) { myInternalClipboard = myInternalClipboard + myCell.Value.ToString(); IsNewRecord = false; } else myInternalClipboard = myInternalClipboard + "\t" + myCell.Value.ToString(); } IsNewRecord = true; myInternalClipboard = myInternalClipboard + "\r\n"; } Clipboard.Clear(); Clipboard.SetText(myInternalClipboard); }
This allows the end-user to select a column or a range of columns and copy those values to the clipboard. It was interesting to implement as when you select a field, you’re not actually selecting the cells in that field, but the entire field. So, you actually have to loop through all the records and build your clipboard string based on the parameters of the selected fields:
private static void CopySelectedFields(Infragistics.Windows.DataPresenter.XamDataGrid myGrid) { string myInternalClipboard = null; bool IsNewRecord = true; Infragistics.Windows.DataPresenter.SelectedFieldCollection mySelectedFields = myGrid.SelectedItems.Fields; foreach (DataRecord myRecord in myGrid.Records) { foreach (Field myField in mySelectedFields) { if (myInternalClipboard == null || IsNewRecord == true) { myInternalClipboard = myInternalClipboard + myRecord.Cells[myField].Value.ToString(); IsNewRecord = false; } else { myInternalClipboard = myInternalClipboard + "\t" + myRecord.Cells[myField].Value.ToString(); } } IsNewRecord = true; myInternalClipboard = myInternalClipboard + "\r\n"; } Clipboard.Clear(); Clipboard.SetText(myInternalClipboard); }
That’s it. After adding this simple code to your application, you can now allow your end-users to copy from the XamDataGrid to an Excel file or to any Windows Application. You can download the code for this example here.