WPF - insufficient memory when doing copy/paste vs

2020-04-16 02:01发布

I have a TreeView that provides drag and drop as well as copy/paste functionality. I extended TreeViewItem to provide that functionality.

The drag and drop works fine. The tree is bound to a view model, and the drag is initiated in the TreeViewItem custom class such as:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        // ...
        if (canDrag)
        {
            DragDrop.DoDragDrop(this, DataContext, DragDropEffects.Copy);
            e.Handled = true;
        }
    }

The drop is initiated such as:

    protected override void OnDrop(DragEventArgs e)
    {
        // ...
        Paste(e.Data);
        e.Handled = true;
    }

which calls a paste method that takes in an IDataObject such as:

    protected void Paste(IDataObject data)
    {
        // ...
        if (data.GetDataPresent(typeof(FooViewModel)) == true)
        {
            // process Foo drop
            copiedFoo = data.GetData(typeof(FooViewModel)) as FooViewModel;
            // ...
        }
    }

The copy/paste operation is set up as follows. The copy is initiated in the TreeViewItem custom class such as:

    void CopyExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Clipboard.Clear();
        Clipboard.SetData(DataContext.GetType().ToString(), DataContext);
    }

The paste is initiated such as:

    void PasteExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Paste(Clipboard.GetDataObject());
    }

calling the same paste method with IDataObject above.

Issue: The same paste method fails at the GetData() call with an Insufficient memory to continue the execution of the program message when called from a copy/paste operation. I've even passed in an empty view model instance to the clipboard, with the same insufficient memory result.

There has been a known VS2010 issue similar to this, explained here. I installed that hotfix, but the memory issue still persists.

Any ideas? Should I be interacting with the Clipboard differently? Thanks!

1条回答
地球回转人心会变
2楼-- · 2020-04-16 02:24

I had this issue in the past, and it has to do with storing an object in the ClipBoard. I can't remember exactly why, but I needed to serialize my object and store the byte[] in the clipboard instead of the object itself.

The code I used looked something like this:

Writing:

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

Clipboard.SetDataObject(data, true);

Reading:

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

Serialization Classes

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);
    }
}
查看更多
登录 后发表回答