【发布时间】:2021-04-20 16:58:10
【问题描述】:
我已经实现了 ObservableCollection 的深度克隆,以便通过取消按钮将项目重置为可编辑 Datagrid 中的原始状态。
为此,我有两个集合 - 一个 ObservableCollection 将 Datagrid 绑定到它,并克隆 List 以在需要时将 ObservableCollection 重新初始化为它的原始状态。
我的代码仅在我第一次点击取消按钮时才有效,之后我的克隆列表也发生了变化。
提供的代码是一个示例(我的有点长),但它与我的 100% 相同:
实现ICloneable的模型:
public class EmployeeModel : ICloneable
{
public object Clone()
{
return MemberwiseClone();
}
public string NAME
{
get { return _name; }
set
{
if (_name != value)
{
CHANGE = true;
_name = value;
}
}
}
private string _name;
public string SURNAME
{
get { return _surname; }
set
{
if (_surname != value)
{
CHANGE = true;
_surname = value;
}
}
}
private string _surname;
///<summary>Property for tracking changes in model</summary>
public bool CHANGE { get; set; }
}
视图模型:
public ViewModel() : Base //Implements InotifyPropertyChanged
{
public ViewModel()
{
Task.Run(()=> GetData());
}
public ObservableCollection<EmployeeModel> Employees
{
get { return _employees; }
set { _employees = value; OnPropertyChanged();}
}
private ObservableCollection<EmployeeModel> _employees;
public List<EmployeeModel> Copy_employees
{
get { return _copy_employees; }
set { _copy_employees = value; OnPropertyChanged();}
}
private List<EmployeeModel> _copy_employees;
//Fetch data from DB
private async Task Get_data()
{
//Returns new ObservableCollection of type Employee
Employees = await _procedures.Get_employees();
if (Employees != null) //Now make a deep copy of Collection
{
Copy_employees = new List<EmployeeModel>();
Copy_employees = Employees.Select(s => (EmployeeModel)s.Clone()).ToList();
}
}
//My Command for canceling changes (reseting DataGrid)
//CanExecute happens, when model is changed - tracking via CHANGE property of EmployeeModel
public void Cancel_Execute(object parameter)
{
Employees.Clear(); //Tried with re-initializing too, but same result
foreach (var item in Copy_employees)// Reset binded ObservableCollection with old items
{
Employees.Add(item);
}
//Check if copied List really hasn't got any changes
foreach (EmployeeModel item in Copy_employees)
{
Console.WriteLine("Changes are " + item.CHANGES.ToString());
}
}
}
取消命令的输出:
1.) 我第一次点击取消按钮:
// Changes are False
每次:
// Changes are True
所以,正如我从控制台看到的那样,当 ObservableColection 更新时,我复制的列表也会更新,即使它没有绑定到 DataGrid。 它只更新我更改的属性,因此 List 反映 ObservableCollection 项。
我怎样才能保留我的原始项目 List<Employee>,并随时将它们复制到绑定的 ObservableCollection 中?
【问题讨论】:
-
不使用memberwiseclone。这会复制对对象的引用。看一眼。 .stackoverflow.com/questions/78536/deep-cloning-objects 个人而言,我通常使用 automapper 将 dto 复制到视图模型中。
-
@Andy:显示的代码仅包含
EmployeeModel对象中的不可变字段,因此虽然一般来说MemberwiseClone()不会进行深层复制是对的,但实际上在这里没关系。 -
您发布的代码没有显示任何形式的
ToString()覆盖EmployeeModel,因此代码不可能输出任何类似于"Changes are False"的文本。缺少正确的minimal reproducible example,不可能知道实际发生了什么,因此无法为这个问题提供好的答案。 -
@PeterDuniho,我刚刚编辑了它,没看到,抱歉。
-
@Andy,我已经在您提供的链接中尝试了接受的答案,但它不能在 C# 中编译。
标签: wpf observablecollection deep-copy