0
votes

I want to be able to pass a list of objects to a child form, bind this to some controls, edit the properties of the list from these control and then pass back this modified list to the parent form only if the user clicks OK. If user escapes or clicks cancel then I don't want the original list updating.

OK, so I open a child form from my parent from as pass a list to that form as so:

List<Names> nameList = new List<Names>();
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
    using (Form2 fm2 = new Form2(nameList))
    {
        fm2.ShowDialog();
        if (fm2.NameListProperty != null)
        {
            nameList = fm2.NameListProperty;
        }            
    }
}

On my Child Form, Form2, I bind the list to a ListBox and a TextBox:

List<Names> nameList = new List<Names>();

public List<Names> NameListProperty { get; set; }

public Form2(List<Names> nameListPassed)
{
    InitializeComponent();

    nameList = nameListPassed;

    BindingSource bs = new BindingSource();
    bs.DataSource = nameList;
    listBoxNames.DataSource = bs;
    listBoxNames.DisplayMember = "FullName";                
    txtSurname.DataBindings.Add("Text", bs, "Surname", true, DataSourceUpdateMode.OnPropertyChanged);       
}

Then finally when the user clicks the OK button the property is set to the modified nameList. If the user does not click Ok, i.e. escapes or clicks Cancel, then the property is not set and remains as null and should not be assigned back to the master nameList on the parent form, Form1.

private void btnOK_Click(object sender, EventArgs e)
{
    NameListProperty = nameList;
    this.Close();
}

However, the problem is that the list on the parent form is updated no matter how the user closes the child form. The Property that is used to pass the list back to the parent form is obsolete as the list on the parent form is updated anyway. I guess my question is how to stop this from happening so that I can select whether changes in the child form are passed back to the parent form.

1
Hey. Have you tried this. See link link for capturing dialog result - T Kelly
Thanks, I tried this but it didn't work. I think the issue is something to do with the databinding linking to the parent form or something. I'm not very familiar with databinding, so I'm not sure. The list in the parent form is updated in line with updates in the child it would seem. - mike7mike

1 Answers

2
votes

The List<Names> is a reference type, so is the Names class. When you pass such a list to the other form, both additions, removals or element updates are automatically reflected, because it's one and the same list/object instances.

In order to achieve the desired behavior, you need to pass a clone of the list. Note that just using nameList.ToList() is not enough because it would create a shallow copy while you really need a deep copy. One possible way is to use something like this

var nameListCopy = nameList.Select(n => new Names
{
    Property1 = n.Property1,
    Property2 = n.Property2,
    // ... the rest of the properties
}).ToList();

using (Form2 fm2 = new Form2(nameListCopy))
// ...

If your Names is as simple data class (does not contain mutable reference type properties/fields), you can use the following

class Names
{
    // ...
    public Names Clone() { return (Names)this.MemberwiseClone(); }
}

and then

var nameListCopy = nameList.Select(n => n.Clone()).ToList();