剪贴板:复制和粘贴对象的方法

12
我正在尝试将一个对象复制到Windows剪贴板上,并再次从其中复制。 我的代码如下:
将其复制到剪贴板:
Clipboard.Clear();
DataObject newObject = new DataObject(prompts);
newObject.SetData(myString);
Clipboard.SetDataObject(newObject);
< p >其中< code >prompts< /code >是一个< code >List<Data.Sources.PromptResult>< /code >集合。< /p > < p >从剪贴板中复制:< /p >
IDataObject dataObject = System.Windows.Forms.Clipboard.GetDataObject();
if (dataObject.GetDataPresent(typeof(List<Data.Sources.PromptResult>)))
{
  Type type = typeof(List<Data.Sources.PromptResult>);
  Object obj = dataObject.GetData(type);
  return (List<Data.Sources.PromptResult>)dataObject.GetData(type);
}
GetFormats() 方法返回的列表中包含了格式,GetDataPresent(List<Data.Sources.PromptResult>) 方法返回 true,但是使用 GetData(List<Data.Sources.PromptResult>) 方法从 Clipboard 类中获取对象时,返回为 null。

有没有人知道可能出了什么问题?


2
我遇到了相同的问题,但我的解决方法不同。我所要做的就是确保对象的每个部分(子对象)都是可序列化的类型。代码量少得多。尝试使用IsSerializable方法!如果你的类不可序列化,异常会很好地描述这个问题。 - Bitterblue
我尝试过类似的东西。正如 Bitterblue 所指出的,有一种简单的方法来测试所提到的类(您刚刚确认带有"[Serializeable]"注释的类)是否确实可序列化。您需要这样做。我不确定我是否在其他地方看到过像他的参考那样清楚地说明:"您的类的第一个和唯一的剪贴板要求。您的类必须是可序列化的"。 - msr
5个回答

17

好的,我尝试将我的用户类型列表添加到剪贴板并获取它回来...

这是我尝试过的:

我的用户类:

public class User
{
   public int Age { get; set; }
   public string Name { get; set; }
}

代码的其余部分:

// Create User list and add some users
List<User> users = new List<User>();
users.Add(new User { age = 15, name = "Peter" });
users.Add(new User { age = 14, name = "John" });

// Lets say its my data format
string format = "MyUserList";
Clipboard.Clear();

// Set data to clipboard
Clipboard.SetData(format, users);

// Get data from clipboard
List<User> result = null;
if (Clipboard.ContainsData(format))
    result = (List<User>)Clipboard.GetData(format);

......结果是null :) 直到我将User类标记为Serializable

[Serializable]
public class User
{ 
    //...   
}

之后我的代码就可以工作了。 好吧,这不是答案,但或许可以在某种程度上帮到你。


可以,Serializable接口用于序列化类。我通常使用XML序列化,但是我猜Clipboard类使用二进制序列化。 - James
1
是的,它使用二进制序列化。 - Renatas M.
我已经尝试过这个,并且似乎可以工作,但是我也想提供文本输出。我认为我可能需要在自己的类上实现IDataObject接口。我之所以这样认为,是因为如果我将DataObject设置为我的序列化对象和文本字符串,那么当尝试获取数据时,我的对象就会丢失。我认为这可能是DataObject的SetData方法中的一个错误,或者DataObject类本身不可序列化。 - James
你还需要使任何子属性对象可序列化,否则复制将失败。谢谢提示!我的复制现在可以工作了。 - Kezzla

4

@Reniuz感谢你的帮助,它帮助我找到了答案。

为了从具有多种格式的剪贴板中获取文本和自定义对象数据,我已经在我的类中实现了IDataObject接口。设置数据对象的代码必须设置复制标志,如下所示:

Clipboard.Clear();
Clipboard.SetDataObject(myClassThatImplementsIDataObject, true);

为了重新获取数据,可以使用标准文本进行检索:
Clipboard.GetText();

数据可以使用 data 方法检索:
Clipboard.GetData("name of my class");

另一个有帮助的建议是使用BinaryFormatter类测试我要放入剪贴板的对象是否可以序列化,如果抛出异常,则默默地失败,无法复制到剪贴板。
所以我的类包括:
[Serializable]
public class ClipboardPromptsHolder : IDataObject
{
    ...
}

3

我遇到过类似的情况,在将我的类标记为可序列化之后,我成功解决了它。

因此,请尝试在你的类Data.Sources.PromptResult上放置Serializable属性。


0
我发现,如果你的类是从另一个类派生而来的,那么基类也需要被标记为[Serializable],否则这个方法就不起作用了。在我的情况下,就像这样:
public abstract class MyAbstractUser
{
...
}

[Serializable]
public class MyUser : MyAbstractUser
{
...
}

当我尝试通过剪贴板交换MyUser的值时,它没有起作用,但是当我在MyAbstractUser上添加[Serializable]时,它就可以工作了。

0

在尝试将项目列表发送到剪贴板时,我遇到了这个问题。我需要的是这些项目的字符串表示形式,而不是整个对象。我尝试了这里的一些建议,但都没有成功。然而,我想出了自己的解决方案,并想分享一下。请参见以下内容。

public static void CopyToClipboard<T>(this IEnumerable<T> items)
{
    StringBuilder stringBuilder = new StringBuilder();

    foreach (T item in items)
        stringBuilder.Append(item.ToString()).AppendLine();

    Clipboard.SetText(stringBuilder.ToString());
}

将此内容作为扩展方法添加,并确保覆盖您自定义类型的 ToString() 方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接