数据和数据对象

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

  • 一个 Object 包含实际数据。

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

数据本身可以包含可表示为基 Object的任何内容。 相应的数据格式是一个字符串,或者 Type 提供有关数据格式的提示。 数据对象支持托管多个数据/数据格式对;这使单个数据对象能够以多种格式提供数据。

数据对象

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

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

WPF 在DataObject类中提供IDataObject的基本实现。 股票 DataObject 类足以满足许多常见的数据传输方案。

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

数据对象通常包括一种工具,用于在提取数据时自动将存储在一种格式中的数据转换为其他格式;此设施称为自动转换。 在查询数据对象中的可用数据格式时,可以通过调用 GetFormats(Boolean)GetDataPresent(String, Boolean) 方法,并将 autoConvert 参数指定为 false,以区分自动转换的数据格式和本机数据格式。 使用 SetData(String, Object, Boolean) 该方法将数据添加到数据对象时,可以通过将参数设置为 autoConvertfalse 来禁止自动转换数据。

处理数据对象

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

创建新数据对象

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 两次将导致数据/数据格式在数据对象中出现两次。