Reputation: 191
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.
Upvotes: 0
Views: 896
Reputation: 1105
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
Upvotes: 1