WPF-对视图模型数据执行复制/粘贴与拖放时内存不足

WPF-对视图模型数据执行复制/粘贴与拖放时内存不足,wpf,mvvm,drag-and-drop,treeview,copy-paste,Wpf,Mvvm,Drag And Drop,Treeview,Copy Paste,我有一个TreeView,它提供拖放和复制/粘贴功能。我扩展了TreeViewItem,以提供该功能 拖放操作工作正常。树绑定到视图模型,并在treevieItem自定义类中启动拖动,例如: protected override void OnMouseMove(MouseEventArgs e) { // ... if (canDrag) { DragDrop.DoDragDrop(this, DataCo

我有一个
TreeView
,它提供拖放和复制/粘贴功能。我扩展了
TreeViewItem
,以提供该功能

拖放操作工作正常。树绑定到视图模型,并在
treevieItem
自定义类中启动拖动,例如:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        // ...
        if (canDrag)
        {
            DragDrop.DoDragDrop(this, DataContext, DragDropEffects.Copy);
            e.Handled = true;
        }
    }
    void CopyExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Clipboard.Clear();
        Clipboard.SetData(DataContext.GetType().ToString(), DataContext);
    }
该下降被启动,例如:

    protected override void OnDrop(DragEventArgs e)
    {
        // ...
        Paste(e.Data);
        e.Handled = true;
    }
    void PasteExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Paste(Clipboard.GetDataObject());
    }
它调用一个粘贴方法,该方法接收
IDataObject
,例如:

    protected void Paste(IDataObject data)
    {
        // ...
        if (data.GetDataPresent(typeof(FooViewModel)) == true)
        {
            // process Foo drop
            copiedFoo = data.GetData(typeof(FooViewModel)) as FooViewModel;
            // ...
        }
    }
复制/粘贴操作的设置如下所示。在
treevieItem
自定义类中启动复制,例如:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        // ...
        if (canDrag)
        {
            DragDrop.DoDragDrop(this, DataContext, DragDropEffects.Copy);
            e.Handled = true;
        }
    }
    void CopyExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Clipboard.Clear();
        Clipboard.SetData(DataContext.GetType().ToString(), DataContext);
    }
将启动粘贴,例如:

    protected override void OnDrop(DragEventArgs e)
    {
        // ...
        Paste(e.Data);
        e.Handled = true;
    }
    void PasteExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Paste(Clipboard.GetDataObject());
    }
使用上面的
IDataObject
调用相同的粘贴方法

问题:相同的粘贴方法在调用
GetData()
时失败,内存不足,无法在从复制/粘贴操作调用时继续执行程序消息。我甚至将一个空的视图模型实例传递到剪贴板,同样的结果是内存不足

有一个已知的VS2010问题与此类似,解释道。我安装了该修补程序,但内存问题仍然存在


有什么想法吗?我是否应该以不同的方式与
剪贴板进行交互?谢谢

我以前遇到过这个问题,它与在剪贴板中存储对象有关。我不记得确切的原因,但我需要序列化我的对象,并将
字节[]
存储在剪贴板中,而不是对象本身

我使用的代码如下所示:

写作:

byte[] data = SerializationHelpers.SerializeToBinary<TreeNodeBase>(
    selectedTreeNode, 
    new Type[] { typeof(TreeNodeA), typeof(TreeNodeB),typeof(TreeNodeC)}
);

Clipboard.SetDataObject(data, true);
byte[]data=SerializationHelpers.SerializationToBinary(
选定的重节点,
新类型[]{typeof(TreeNodeA),typeof(TreeNodeB),typeof(TreeNodeC)}
);
剪贴板.SetDataObject(数据,真);
阅读:

IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(typeof(byte[])))
{
    MyClass obj = SerializationHelpers.DeserializeFromBinary<TreeNodeBase>(
        (byte[])data.GetData(typeof(byte[])), 
        new Type[] {typeof(TreeNodeA), typeof(TreeNodeB),typeof(TreeNodeC)}
    );
}
IDataObject data=Clipboard.GetDataObject();
if(data.GetDataPresent(typeof(byte[]))
{
MyClass obj=SerializationHelpers.DeserializeFromBinary(
(byte[])data.GetData(typeof(byte[]),
新类型[]{typeof(TreeNodeA),typeof(TreeNodeB),typeof(TreeNodeC)}
);
}
序列化类

public static byte[] SerializeToBinary<T>(T obj, Type[] extraTypes)
{
    if (obj == null)
        return null;

    using (MemoryStream ms = new MemoryStream())
    {
        DataContractSerializer dcs = new DataContractSerializer(typeof(T), extraTypes);
        dcs.WriteObject(ms, obj);
        return ms.ToArray();
    }
}

public static T DeserializeFromBinary<T>(byte[] data, Type[] extraTypes)
{
    if (data.Length == 0)
        return default(T);

    using (MemoryStream ms = new MemoryStream())
    {
        ms.Write(data, 0, data.Length);
        ms.Seek(0, 0);

        DataContractSerializer dcs = new DataContractSerializer(typeof(T), extraTypes);
        return (T)dcs.ReadObject(ms);
    }
}
publicstaticbyte[]SerializeToBinary(T obj,Type[]extractypes)
{
if(obj==null)
返回null;
使用(MemoryStream ms=new MemoryStream())
{
DataContractSerializer dcs=新的DataContractSerializer(typeof(T),extraTypes);
dcs.WriteObject(ms,obj);
返回ToArray女士();
}
}
公共静态T反序列化FromBinary(字节[]数据,类型[]外部类型)
{
如果(data.Length==0)
返回默认值(T);
使用(MemoryStream ms=new MemoryStream())
{
ms.Write(数据,0,数据长度);
Seek女士(0,0);
DataContractSerializer dcs=新的DataContractSerializer(typeof(T),extraTypes);
返回(T)dcs.ReadObject(ms);
}
}

您解决的VS2010问题是VS2010应用程序本身的问题。这是另外一件事……你真的应该把这种东西放到剪贴板上吗?@Paul,谢谢。视图模型占用的空间足够小,因此将其放入DataObject进行拖放似乎不是问题。数据对象的剪贴板处理是否更占用内存?我以前遇到过这个问题,我真的不记得是如何解决的。我相信这与在内存中存储一个对象有关,我想我最终序列化了这个对象,但我不是肯定的。@Rachel,谢谢。如果没有更简单的方法,我想尝试序列化视图模型并从剪贴板中获取文本。剪贴板意味着COM。您的ViewModel及其组件是否可见?如果我没有弄错的话,它也应该是可序列化的,或者可以通过值进行复制。+1感谢您提供了一种序列化方法,我可能会采用这种方法。这种方法的一个小问题是,我还需要将数据类型传递到剪贴板,因为不同的树节点具有不同的类型,可能会将其作为剪贴板文本传递?树节点是否继承自相同的基类型?如果是这样,您可以简单地将对象强制转换为基类型。如果在序列化/反序列化时包含基类型的任何子类型,应该不会有问题。是的,我有一个通用的基类型,并且可以传递一长串子类型。我现在的主要问题是(与我的模型类不同),我的视图模型类不是设计为可序列化的,所以需要做一些返工!