数据和数据对象

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

  • 包含实际数据的 Object 对象。

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

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

数据对象

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

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

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

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

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

使用数据对象

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

创建新数据对象

DataObject 类提供了多个重载构造函数,这些构造函数有助于使用一个数据/数据格式对来初始化新的 DataObject 实例。

以下示例代码创建一个新的数据对象,并使用其中一个重载构造函数 DataObjectDataObject(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 两次将导致数据/数据格式在数据对象中出现两次。