Ask Kathleen
Serialize Data to the Clipboard
Learn how to copy all the custom data formats in objects to the clipboard and determine which ones are appropriate when you paste.
Technology Toolbox: VB.NET, C#
Q. How do I copy the current object (record) in WinForms? My users want to use an existing record as the starting point for new records and sometimes copy records between forms. The problem is that forms can have multiple types of data on them, and I don't know which piece of data the user wants to copy.
A. The easiest way to solve this is to copy all the potential sources into the clipboard with different custom formats and determine which ones are appropriate when you paste.
The clipboard allows any format you might want to use. You mark each with a string identifier that indicates the format. The format identifier needs to be recognized by the application trying to retrieve data from the clipboard, or the data will not be retrieved. Standard clipboard format strings are available as static fields in the DataFormats class, so you don't have to remember the well-known strings. Use these when you're storing common data formats such as strings or images. Use a unique name when you're using custom formats, such as directly storing data objects; this unique name can be anything other than one of the standard format names.
You can store multiple data representations in the clipboard. If you need to control what data is copied to protect sensitive information, consider custom serialization. Otherwise, you can store the objects directly. By convention, the clipboard holds a single piece of data in multiple formats. I'm suggesting a variation of this idea; you'll be storing multiple subparts of the displayed data. I don't think you'll confuse other applications because they won't recognize your customer format identifiers.
To see this in practice, you can create a simple application that uses an MDI Parent and simplified child forms. This design lets you create multiple instances of the child form and copy records between them for testing. You can also open multiple instances and copy between them. Menu items access the cut record and paste record features in the sample application, which you can also wire to buttons and keystrokes. I think users will expect Ctrl-C and Ctrl-V to cut and paste from individual controls, so you probably want to use other keystrokes.
Putting text to the clipboard is easy with the Clipboard.SetText method. This is basically the same as using SetData with the Text format string:
Clipboard.SetText(data.ToString());
Clipboard.SetData(DataFormats.Text, data.ToString());
Clipboard.SetData("Text", data.ToString());
Both approaches put text in the clipboard as a .NET string, text, and Unicode. Additional clipboard methods such as SetAudio and SetImage put other data types in the clipboard in appropriate formats. All of the clipboard set methods assume you want to put a new item in the clipboard, so they clear any other existing data formats.
The clipboard set, get, and contains methods access the underlying DataObject. To place multiple formats in the clipboard, you need to create a DataObject directly (Listing 1.) The key difference between the set methods available on the clipboard and those available on the DataObject is that existing formats are not cleared in the DataObject.
The DataObject is used both for clipboard operations and for drag/drop operations, so you should isolate the code that does the real work from the code that creates and retrieves the data object. The real work in the online sample occurs in the private BuildDataObject and FillFromDataObject methods. The BuildDataObject method creates a DataObject, fills it with data in several formats, and returns the new DataObject. The FillFromDataObject method sets the current record based on one of the custom formats in the clipboard. The Copy and Paste methods move data on and off the clipboard and call the BuildDataObject and FillFromDataObject methods. The download includes code for a second form that stores a DataTable and DataRow to the clipboard. It can accept either format and asks the user which to use on paste. You could also offer a "Paste Special" menu option or button that gives the user several options.
Interacting with the clipboard solves only one part of the problem. You also need a reusable way to access the clipboard. You could include the copy and paste menu items in each form and merge the menus, but the work of correctly enabling and localizing menu items and buttons would have to be repeated. Instead, you can add the menu functionality to the MDI parent and create an interface for forms that defines the copy and paste operations:
public interface IClipboardSupport
{
void CopyData();
void PasteData();
}
The menu click event handlers check whether the current form implements the interface and calls the appropriate method:
private void copyRecordToolStripMenuItem_Click(
object sender, EventArgs e)
{
IClipboardSupport form =
this.ActiveMdiChild as IClipboardSupport;
if (form != null)
{
form.CopyData();
}
}
Objects placed on the clipboard must be serializable. Unfortunately, .NET doesn't raise an exception if you place a non-serializable object in the clipboard or data object. It includes the format, but stores null. This makes it look like the clipboard isn't working. If your object can't be serialized, consider creating a byte array and storing it in the clipboard as a memory stream. You will also have to retrieve it as a memory stream and reconstitute the object from the byte array.
Serializing data to the clipboard is a quick and effective solution to copying records, but be careful how you handle sensitive information. Your user can generally copy the information that is displayed to them, but sometimes business objects retrieve sensitive data and don't show it. In this case, you do not want to serialize all the data if your user might have another program that could deserialize the clipboard object and discover the sensitive information.
The clipboard in WPF works essentially the same way as the one in WinForms, but with the significant enhancement that the data object has Copying, Pasting, and SettingData events. These events give you more control over the clipboard operations, including the ability to cancel each operation and to apply data conversions between formats on paste.
About the Author
Kathleen is a consultant, author, trainer and speaker. She’s been a Microsoft MVP for 10 years and is an active member of the INETA Speaker’s Bureau where she receives high marks for her talks. She wrote "Code Generation in Microsoft .NET" (Apress) and often speaks at industry conferences and local user groups around the U.S. Kathleen is the founder and principal of GenDotNet and continues to research code generation and metadata as well as leveraging new technologies springing forth in .NET 3.5. Her passion is helping programmers be smarter in how they develop and consume the range of new technologies, but at the end of the day, she’s a coder writing applications just like you. Reach her at [email protected].