Search code examples
c#clipboardserializableidataobject

IDataObject.GetData() always returns null with my class


I have a class which I marked as [Serializable] that I'm trying to copy through the clipboard. Calling GetData() always returns null.

Copy code:

IDataObject dataObject = new DataObject();
dataObject.SetData("MyClass", false, myObject);
Clipboard.SetDataObject(dataObject, true);

Paste code:

if (Clipboard.ContainsData("MyClass"))
{
    IDataObject dataObject = Clipboard.GetDataObject();

    if (dataObject.GetDataPresent("MyClass"))
    {
        MyClass myObject = (MyClass)dataObject.GetData("MyClass");
        // myObject is null
    }
}

MyClass is actually a derived class. Both it and its base are flagged as [Serializable]. I tried the same code with a simple test class and it worked.

MyClass contains GraphicsPath, Pen, Brush, and arrays of value types.


Solution

  • The Pen class is not marked as serializable, and also inherits from MarshalByRefObject.

    You will need to implement ISerializable and handle these types of objects

    [Serializable]
    public class MyClass : ISerializable
    {
        public Pen Pen;
    
        public MyClass()
        {
            this.Pen = new Pen(Brushes.Azure);
        }
    
        #region ISerializable Implemention
    
        private const string ColorField = "ColorField";
    
        private MyClass(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");
    
            SerializationInfoEnumerator enumerator = info.GetEnumerator();
            bool foundColor = false;
            Color serializedColor = default(Color);
    
            while (enumerator.MoveNext())
            {
                switch (enumerator.Name)
                {
                    case ColorField:
                        foundColor = true;
                        serializedColor = (Color) enumerator.Value;
                        break;
    
                    default:
                        // Ignore anything else... forwards compatibility
                        break;
                }
            }
    
            if (!foundColor)
                throw new SerializationException("Missing Color serializable member");
    
            this.Pen = new Pen(serializedColor);
        }
    
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(ColorField, this.Pen.Color);
        }
        #endregion
    }