Data and Data Objects

Updated: April 2011

Data that is transferred as part of a drag-and-drop operation is stored in a data object. Conceptually, a data object consists of one or more of the following pairs:

  • An Object that contains the actual data.

  • A corresponding data format identifier.

The data itself can consist of anything that can be represented as a base Object. The corresponding data format is a string or Type that provides a hint about what format the data is in. Data objects support hosting multiple data/data format pairs; this enables a single data object to provide data in multiple formats.

Data Objects

All data objects must implement the IDataObject interface, which provides the following standard set of methods that enable and facilitate data transfer.

Method

Summary

GetData

Retrieves a data object in a specified data format.

GetDataPresent

Checks to see whether the data is available in, or can be converted to, a specified format.

GetFormats

Returns a list of formats that the data in this data object is stored in, or can be converted to.

SetData

Stores the specified data in this data object.

WPF provides a basic implementation of IDataObject in the DataObject class. The stock DataObject class is sufficient for many common data transfer scenarios.

There are several pre-defined formats, such as bitmap, CSV, file, HTML, RTF, string, text, and audio. For information about pre-defined data formats provided with WPF, see the DataFormats class reference topic.

Data objects commonly include a facility for automatically converting data stored in one format to a different format while extracting data; this facility is referred to as auto-convert. When querying for the data formats available in a data object, auto-convertible data formats can be filtered from native data formats by calling the GetFormats or GetDataPresent method and specifying the autoConvert parameter as false. When adding data to a data object with the SetData method, auto-conversion of data can be prohibited by setting the autoConvert parameter to false.

Working with Data Objects

This section describes common techniques for creating and working with data objects.

Creating New Data Objects

The DataObject class provides several overloaded constructors that facilitate populating a new DataObject instance with a single data/data format pair.

The following example code creates a new data object and uses one of the overloaded constructors DataObject(DataObject) to initialize the data object with a string and a specified data format. In this case, the data format is specified by a string; the DataFormats class provides a set of pre-defined type strings. Auto-conversion of the stored data is allowed by default.

Dim stringData As String = "Some string data to store..."
Dim dataFormat As String = DataFormats.UnicodeText
Dim dataObject As New DataObject(dataFormat, stringData)
string stringData = "Some string data to store...";
string dataFormat = DataFormats.UnicodeText;
DataObject dataObject = new DataObject(dataFormat, stringData);

For more examples of code that creates a data object, see How to: Create a Data Object.

Storing Data in Multiple Formats

A single data object is able to store data in multiple formats. Strategic use of multiple data formats within a single data object potentially makes the data object consumable by a wider variety of drop targets than if only a single data format could be represented. Note that, in general, a drag source must be agnostic about the data formats that are consumable by potential drop targets.

The following example shows how to use the SetData method to add data to a data object in multiple formats.

                Dim dataObject As New DataObject()
                Dim sourceData As String = "Some string data to store..."

                ' Encode the source string into Unicode byte arrays.
                Dim unicodeText() As Byte = Encoding.Unicode.GetBytes(sourceData) ' UTF-16
                Dim utf8Text() As Byte = Encoding.UTF8.GetBytes(sourceData)
                Dim utf32Text() As Byte = Encoding.UTF32.GetBytes(sourceData)

                ' The DataFormats class does not provide data format fields for denoting
                ' UTF-32 and UTF-8, which are seldom used in practice; the following strings 
                ' will be used to identify these "custom" data formats.
                Dim utf32DataFormat As String = "UTF-32"
                Dim utf8DataFormat As String = "UTF-8"

                ' Store the text in the data object, letting the data object choose
                ' the data format (which will be DataFormats.Text in this case).
                dataObject.SetData(sourceData)
                ' Store the Unicode text in the data object.  Text data can be automatically
                ' converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object; 
                ' Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
                ' is done here as an exercise only.
                dataObject.SetData(DataFormats.UnicodeText, unicodeText)
                ' Store the UTF-8 text in the data object...
                dataObject.SetData(utf8DataFormat, utf8Text)
                ' Store the UTF-32 text in the data object...
                dataObject.SetData(utf32DataFormat, utf32Text)
DataObject dataObject = new DataObject();
string sourceData = "Some string data to store...";

// Encode the source string into Unicode byte arrays.
byte[] unicodeText = Encoding.Unicode.GetBytes(sourceData); // UTF-16
byte[] utf8Text = Encoding.UTF8.GetBytes(sourceData);
byte[] utf32Text = Encoding.UTF32.GetBytes(sourceData);

// The DataFormats class does not provide data format fields for denoting
// UTF-32 and UTF-8, which are seldom used in practice; the following strings 
// will be used to identify these "custom" data formats.
string utf32DataFormat = "UTF-32";
string utf8DataFormat  = "UTF-8";

// Store the text in the data object, letting the data object choose
// the data format (which will be DataFormats.Text in this case).
dataObject.SetData(sourceData);
// Store the Unicode text in the data object.  Text data can be automatically
// converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object; 
// Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
// is done here as an exercise only.
dataObject.SetData(DataFormats.UnicodeText, unicodeText);
// Store the UTF-8 text in the data object...
dataObject.SetData(utf8DataFormat, utf8Text);
// Store the UTF-32 text in the data object...
dataObject.SetData(utf32DataFormat, utf32Text);

Querying a Data Object for Available Formats

Because a single data object can contain an arbitrary number of data formats, data objects include facilities for retrieving a list of available data formats.

The following example code uses the GetFormats overload to get an array of strings denoting all data formats available in a data object (both native and by auto-convert).

Dim dataObject As New DataObject("Some string data to store...")

' Get an array of strings, each string denoting a data format
' that is available in the data object.  This overload of GetDataFormats
' returns all available data formats, native and auto-convertible.
Dim dataFormats() As String = dataObject.GetFormats()

' Get the number of data formats present in the data object, including both
' auto-convertible and native data formats.
Dim numberOfDataFormats As Integer = dataFormats.Length

' To enumerate the resulting array of data formats, and take some action when
' a particular data format is found, use a code structure similar to the following.
For Each dataFormat As String In dataFormats
    If dataFormat = System.Windows.DataFormats.Text Then
        ' Take some action if/when data in the Text data format is found.
        Exit For
    ElseIf dataFormat = System.Windows.DataFormats.StringFormat Then
        ' Take some action if/when data in the string data format is found.
        Exit For
    End If
Next dataFormat
DataObject dataObject = new DataObject("Some string data to store...");

// Get an array of strings, each string denoting a data format
// that is available in the data object.  This overload of GetDataFormats
// returns all available data formats, native and auto-convertible.
string[] dataFormats = dataObject.GetFormats();

// Get the number of data formats present in the data object, including both
// auto-convertible and native data formats.
int numberOfDataFormats = dataFormats.Length;

// To enumerate the resulting array of data formats, and take some action when
// a particular data format is found, use a code structure similar to the following.
foreach (string dataFormat in dataFormats)
{
    if (dataFormat == DataFormats.Text)
    {
        // Take some action if/when data in the Text data format is found.
        break;
    }
    else if(dataFormat == DataFormats.StringFormat)
    {
        // Take some action if/when data in the string data format is found.
        break;
    }
}

For more examples of code that queries a data object for available data formats, see How to: List the Data Formats in a Data Object. For examples of querying a data object for the presence of a particular data format, see How to: Determine if a Data Format is Present in a Data Object.

Retrieving Data from a Data Object

Retrieving data from a data object in a particular format simply involves calling one of the GetData methods and specifying the desired data format. One of the GetDataPresent methods can be used to check for the presence of a particular data format. GetData returns the data in an Object; depending on the data format, this object can be cast to a type-specific container.

The following example code uses the GetDataPresent overload to check if a specified data format is available (native or by auto-convert). If the specified format is available, the example retrieves the data by using the GetData method.

Dim dataObject As New DataObject("Some string data to store...")

Dim desiredFormat As String = DataFormats.UnicodeText
Dim data() As Byte = Nothing

' Use the GetDataPresent method to check for the presence of a desired data format.
' This particular overload of GetDataPresent looks for both native and auto-convertible 
' data formats.
If dataObject.GetDataPresent(desiredFormat) Then
    ' If the desired data format is present, use one of the GetData methods to retrieve the
    ' data from the data object.
    data = TryCast(dataObject.GetData(desiredFormat), Byte())
End If
DataObject dataObject = new DataObject("Some string data to store...");

string desiredFormat = DataFormats.UnicodeText;
byte[] data = null;

// Use the GetDataPresent method to check for the presence of a desired data format.
// This particular overload of GetDataPresent looks for both native and auto-convertible 
// data formats.
if (dataObject.GetDataPresent(desiredFormat))
{
    // If the desired data format is present, use one of the GetData methods to retrieve the
    // data from the data object.
    data = dataObject.GetData(desiredFormat) as byte[];
}

For more examples of code that retrieves data from a data object, see How to: Retrieve Data in a Particular Data Format.

Removing Data From a Data Object

Data cannot be directly removed from a data object. To effectively remove data from a data object, follow these steps:

  1. Create a new data object that will contain only the data you want to retain.

  2. "Copy" the desired data from the old data object to the new data object. To copy the data, use one of the GetData methods to retrieve an Object that contains the raw data, and then use one of the SetData methods to add the data to the new data object.

  3. Replace the old data object with the new one.

Note

The SetData methods only add data to a data object; they do not replace data, even if the data and data format are exactly the same as a previous call. Calling SetData twice for the same data and data format will result in the data/data format being present twice in the data object.

Change History

Date

History

Reason

April 2011

Added topic.

Customer feedback.