我希望能够将对象列表传递给子窗体,将其绑定到某些控件,从这些控件编辑列表的属性,然后仅在用户单击时将此修改后的列表传回父窗体好。如果用户转义或单击取消,则我不希望原始列表更新。
好的,所以我从父母那里打开一个子表单,将列表传递给该表单,如下所示:
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;
}
}
}
在我的子表单Form2
上,我将列表绑定到ListBox和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);
}
然后,当用户单击“确定”按钮时,该属性将设置为已修改的nameList。如果用户未单击“确定”,即转义或单击“取消”,则不会设置该属性并保持为null
,并且不应将其分配回父窗体Form1上的主名称列表。
private void btnOK_Click(object sender, EventArgs e)
{
NameListProperty = nameList;
this.Close();
}
但是,问题是无论用户如何关闭子表单,父表单上的列表都会更新。用于将列表传递回父表单的属性已过时,因为无论如何父表单上的列表都会更新。我想我的问题是如何阻止这种情况发生,以便我可以选择是否将子表单中的更改传递回父表单。
答案 0 :(得分:2)
List<Names>
是reference type,Names
类也是nameList.ToList()
。当您将此类列表传递给另一个表单时,会自动反映添加,删除或元素更新,因为它是同一个列表/对象实例。
为了实现所需的行为,您需要传递列表的克隆。请注意,仅使用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))
// ...
是不够的,因为它会创建浅层副本,而您确实需要深层副本。一种可能的方法是使用这样的东西
Names
如果您的class Names
{
// ...
public Names Clone() { return (Names)this.MemberwiseClone(); }
}
是简单数据类(不包含可变引用类型属性/字段),则可以使用以下
var nameListCopy = nameList.Select(n => n.Clone()).ToList();
然后
list = [one, two, three]
for item in list:
def item():
some_stuff()