数据和数据对象

作为拖放操作的一部分传输的数据存储在数据对象中。 从概念上讲,数据对象由以下一个或多个对组成:

  • 包含实际数据的 Object

  • 相应的数据格式标识符。

数据本身可以包含任何可以表示为基础映像 Object 的内容。 相应的数据格式是一个字符串或 Type,它提供关于数据所采用的格式的提示。 数据对象支持托管多个数据/数据格式对,这使得单个数据对象可以提供多种格式的数据。

数据对象

所有数据对象必须实现 IDataObject 接口,该接口提供以下标准方法集,用于启用和促进数据传输。

方法 总结
GetData 检索指定数据格式的数据对象。
GetDataPresent 查看是否具有指定格式的数据,或者数据是否可以转换为指定格式。
GetFormats 返回存储此数据对象中的数据或可转换为的格式列表。
SetData 在此数据对象中存储指定的数据。

WPF在 DataObject 类中提供 IDataObject 的基本实现。 普通的 DataObject 类足以满足许多常见的数据传输场景。

有多种预定义的格式,例如位图、CSV、文件、HTML、RTF、字符串、文本和音频。 有关 WPF 提供的预定义数据格式的信息,请参阅 DataFormats 类参考主题。

数据对象通常包括在提取数据时自动将存储在一种格式中的数据转换为另一种格式的功能,此功能称为自动转换。 查询数据对象中可用的数据格式时,通过调用 GetFormats(Boolean)GetDataPresent(String, Boolean) 方法并将参数指定 autoConvertfalse 可以从本机数据格式中筛选出自动转换的数据格式。 使用 SetData(String, Object, Boolean) 方法将数据添加到数据对象时,可以通过将参数 autoConvert 设置为 false 来禁止数据的自动转换。

使用数据对象

本部分介绍创建和使用数据对象的常用技术。

创建新数据对象

DataObject 类提供了多个重载构造函数,这些构造函数有助于使用单个数据/数据格式对填充新 DataObject 实例。

以下示例代码创建一个新的数据对象,并使用重载构造函数 DataObject 之一 (DataObject(String, Object)),以字符串和指定的数据格式初始化数据对象。 在这种情况下,数据格式由字符串指定,DataFormats 类提供一组预定义的类型字符串。 默认情况下,允许自动转换存储的数据。

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

有关创建数据对象的更多代码示例,请参阅创建数据对象

以多种格式存储数据

单个数据对象都能以多种格式存储数据。 在单个数据对象中有策略地使用多种数据格式,可能会使数据对象被更广泛的放置目标所使用,而不是只能表示单个数据格式。 请注意,一般情况下,拖动源必须与潜在放置目标可使用的数据格式无关。

以下示例演示了如何使用 SetData(String, Object) 方法以多种格式将数据添加到数据对象。

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);
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)

查询数据对象以获取可用格式

由于单个数据对象可以包含任意数量的数据格式,因此数据对象包括用于检索可用数据格式列表的功能。

以下示例代码使用 GetFormats 重载来获取表示数据对象中可用的所有数据格式的字符串数组(在本机或者通过自动转换)。

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;
    }
}
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

有关查询数据对象以获取可用数据格式的更多代码示例,请参阅列出数据对象中的数据格式。 有关查询数据对象是否存在特定数据格式的示例,请参阅确定数据对象中是否存在数据格式

从数据对象检索数据

从特定格式的数据对象检索数据只需调用 GetData 方法之一并指定所需的数据格式。 可使用 GetDataPresent 方法之一检查是否存在特定的数据格式。 GetData 返回 Object 中的数据。根据数据格式的不同,可以将此对象强制转换为特定于类型的容器。

以下示例代码使用 GetDataPresent(String) 重载来检查指定的数据格式是否可用(在本机或者通过自动转换)。 如果指定格式可用,则该示例使用 GetData(String) 方法检索数据。

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[];
}
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

有关从数据对象检索数据的代码的更多示例,请参阅以特定数据格式检索数据

从数据对象中删除数据

无法直接从数据对象中删除数据。 要有效地从数据对象中删除数据,请执行以下步骤:

  1. 创建一个新的数据对象,该对象仅包含要保留的数据。

  2. 将所需数据从旧数据对象“复制”到新数据对象。 要复制数据,请使用 GetData 方法之一检索包含原始数据的 Object,然后使用 SetData 方法之一将数据添加到新数据对象中。

  3. 将旧数据对象替换为新数据对象。

注意

SetData 方法仅向数据对象添加数据;即使数据和数据格式与前一个调用完全相同,它们也不会替换数据。 对于相同的数据和数据格式,调用 SetData 两次将导致数据/数据格式在数据对象中出现两次。