Search code examples
c#.netwinformsclone

How to override Clone() on a WinForms DataGridViewCell?


I am creating a DataGridViewCalendarCell based on this MSDN sample and I want to override the Clone of the base class DataGridViewTextBoxCell because I have added two properties to DataGridViewCalendarCell. The problem is that I'm not sure of how to go about this.

Why I think I need to override Clone:

The DateTimePicker has two properties: CustomFormat and Format that I want to expose on through properties on my CalendarColumn Class that I can set when initializing the CalendarColumn. These properties will then set the properties on the DataGridViewCalendarCell that the column uses as a template like so:

public string CustomFormat { 
    get {
        return ((DataGridViewCalendarCell)base.CellTemplate).CustomFormat;
    }
    set {
        ((DataGridViewCalendarCell)base.CellTemplate).CustomFormat = value;
    }
}

public DateTimePickerFormat Format {
    get {
        return ((DataGridViewCalendarCell)base.CellTemplate).Format;
    }
    set {
        ((DataGridViewCalendarCell)base.CellTemplate).Format = value;
    }
}

In the DataGridViewCalendarCell.InitializeEditingControl function the properties are again passed on to the DateTimePicker used to edit the cell value.

The problem I have is that when DataGridViewCalendarCell.InitializeEditingControl is called the Format and CustomFormat are not set anymore.

I am guessing this is because the actual DataGridViewCalendarCells are clones of the template. As I didn't override the Clone method of DateGridViewTextBoxCell, my extra properties are not cloned as well.

Also, there is a nice note in the MSDN article:

When you derive from DataGridViewCell or DataGridViewColumn and add new properties to the derived class, be sure to override the Clone method to copy the new properties during cloning operations. You should also call the base class's Clone method so that the properties of the base class are copied to the new cell or column.

Why I don't know how to override Clone:

This makes me feel like there is a standard way to do this for WinForms controls, but I can't find anything about it.

There is no copy constructor on DataGridViewTextBoxCell to which I can pass the clone returned from base.Clone(). I prefer not to use Reflection because I'm not sure how to tell which properties I should and shouldn't copy. I wonder if I could do something with serialization, but I am afraid of any side effects that I can't oversee, right now.

Is there a standard way to override Clone on a custom control?

EDIT: I editted the question title because the cloning is not relevant for all custom controls, just for DataGridViewCells


Solution

  • Based on this answer to another question about cloning.

    The other approach is to use Object.MemberwiseClone in the implementation of Clone - this will ensure that result is always of the correct type, and will allow overrides to extend

    Apparently DataGridViewTextBoxCell is using Object.MemberwiseClone because I was able to cast the result of base.Clone() to DataGridViewCalendarCell.

    Here is my implementation of Clone() that did the trick:

    class DataGridViewCalendarCell : DataGridViewTextBoxCell
    {
        (...)
    
        public string CustomFormat { get; set; }
        public DateTimePickerFormat Format { get; set; }
    
        public override object Clone()
        {
            var clone = (DataGridViewCalendarCell)base.Clone();
    
            clone.Format = Format;
            clone.CustomFormat = CustomFormat;
    
            return clone;
        }
    }