ObservableCollection 深度克隆
ObservableCollection deep cloning
我已经实现了 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 中?
当您 return 值时,您不会 return 它们,而是将支持项引用写入可编辑集合。
因此,您在两个集合中都有相同的实例。
在最简单的情况下,当你 return 它们时,你还需要克隆。
public void Cancel_Execute(对象参数)
{
Employees.Clear(); //也尝试重新初始化,但结果相同
foreach (var item in Copy_employees)// Reset binded ObservableCollection with old items
{
Employees.Add((EmployeeModel)item.Clone());
}
//Check if copied List really hasn't got any changes
foreach (EmployeeModel item in Copy_employees)
{
Console.WriteLine("Changes are " + item.CHANGES.ToString());
}
}
与问题无关,但我仍然建议您使用更友好的界面进行克隆:
public interface ICloneable<T> : ICloneable
{
new T Clone();
}
我已经实现了 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 中?
当您 return 值时,您不会 return 它们,而是将支持项引用写入可编辑集合。 因此,您在两个集合中都有相同的实例。 在最简单的情况下,当你 return 它们时,你还需要克隆。
public void Cancel_Execute(对象参数) { Employees.Clear(); //也尝试重新初始化,但结果相同
foreach (var item in Copy_employees)// Reset binded ObservableCollection with old items
{
Employees.Add((EmployeeModel)item.Clone());
}
//Check if copied List really hasn't got any changes
foreach (EmployeeModel item in Copy_employees)
{
Console.WriteLine("Changes are " + item.CHANGES.ToString());
}
}
与问题无关,但我仍然建议您使用更友好的界面进行克隆:
public interface ICloneable<T> : ICloneable
{
new T Clone();
}