0

I have a WPF DataGrid bound to an ObservableCollection in my view model. I have context menu action to duplicate the row up or down, that is, insert a new row with the same content above or below the currently-selected row. This all works well and good, but the newly-inserted row seems to be a copy of the other one. Modifying one also modifies its duplicate. This isn't what I want; I want each row to be separate. Here is my code in the view model to duplicate the row downward:

    private void DuplicateDownward()
    {
        CPWrapper row = GetSelectedRow();
        if (row == null)
            return;

        Channels.Insert(SelectedRow + 1, new CPWrapper(row.InnerCP));
    }

Channels is an ObservableCollection<CPWrapper> (with a readonly backing, using only Clears and Inserts), and CPWrapper is a class that wraps around another object (not important). GetSelectedRow returns either the currently selected DataGrid row, or null.

As you can see, I'm inserting a new object from the existing row, and it's still acting like the same object. I even overrode some functions in CPWrapper like such:

public class CPWrapper
{
    private InnerObject cp;

    private static Random rand = new Random();

    private readonly int AntiCopy;

    public CPWrapper()
    {
        cp = new InnerObject();

        AntiCopy = rand.Next();
    }

    public CPWrapper(InnerObject arg)
    {
        cp = arg;

        AntiCopy = rand.Next();
    }

    public override int GetHashCode()
    {
        return AntiCopy.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return false;
    }
}

I was hoping that between GetHashCode from a random integer and Equals always returning false, the system would get the idea that they're not the same.

Any suggestions would be greatly appreciated.

PrinceBilliard
  • 181
  • 1
  • 17
  • No idea what are you trying to do, but read this: [`IEquitable`](http://stackoverflow.com/q/411500/1997232) and [GetHashCode](http://stackoverflow.com/a/263416/1997232). – Sinatr Sep 09 '15 at 14:39

1 Answers1

1

Adding to your InnerObject a copy constructor is the only solution for this. In C# object are referenced. Thus even if your wrapper "thinks" it is a different object the reference towards the "duplicate" points directly towards the "source object".

By doing so you will be sure you are not working with the same object. And remember that each object inside the inner object should have a copy constructor in order for this to work. Otherwise reference towards objects will stay the same.

Additional information. The override for the equals method should be return obj.AntiCopy == this.AntiCopy
otherwise even if you try to know if Wrapper1 == Wrapper1 it will be false. But if you do add the copy constructor the whole wrapper becomes useless in the current case

Daneau
  • 1,085
  • 9
  • 15
  • Adding a copy constructor for InnerObject did indeed fix it, thank you. And my wrapper isn't useless; it has properties and such that are useful for the view model but not needed in the model. – PrinceBilliard Sep 10 '15 at 12:29