mat*_*ven 5 c# linq wpf observablecollection
我正在设计比较列表视图的两个版本,用于设置表单.我需要知道用户是否真的修改了列表,在这种情况下,当他们点击"保存"时,我实际上会保存.如果他们没有改变任何东西,当他们点击"保存"时,我不会浪费记忆/时间重新保存他们没有改变的东西.
无论如何,我如何比较两个ObservableCollections以查看它们是否完全不同?
提前致谢!
您可以使用 LINQ 除外方法:生成两个序列的集差。
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except.aspx
考虑以下示例方法...
public void ExceptFunctioni()
{
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB);
if(aOnlyNumbers.Count()>0)
{
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
在第一个集合上调用 except 方法并将第二个集合作为参数传递。结果将包含差异。然后,您可以查询结果并采取相应措施。如果两个序列相等,则结果的计数将为零。
话虽如此,值得注意的是,MVVM 世界中的首选策略是使用此方法来控制是否启用“保存”按钮。在这种方法中,如果两个集合相等,则“保存”按钮将被禁用并且用户无法访问它。
但无论哪种方式,LINQ 方法都提供了一种非常简洁的方式来实现您的目标……
添加:看到您在回复“Dumb's”评论时所做的评论,您的“oldList”将对应于上面示例代码中的 numbersB...
More succinct: if(numbersA.Except(numbersB).Any()) { // do something }
Run Code Online (Sandbox Code Playgroud)
我们处理这个问题的方式需要预先做更多的工作,但可以使用 VS 宏或 CodeSmith 等代码生成工具来自动化。
然而,这种方法可以扩展到集合绑定到的任何 UI 构造,并且不必在每次需要知道是否有更改时在 UI 中重新实现。
这个概念是更新集合和业务对象内的标志,以确定集合成员身份是否已更改或集合内的任何给定记录是否已更改。
实现相当简单:
将 HasChanged 属性添加到业务对象类。
将 AnyDeleted 属性添加到集合中。仅当从集合中删除项目时才会设置此值。
从数据库读取记录后,将这些值初始化为 false。
(现在是半乏味的部分)对于类中的每个属性,如果值实际发生更改,请将 HasChanged 属性设置为 true。小心空值。例如:
public bool IsSelected
{
get
{
return m_fIsSelected;
}
set
{
if (m_fIsSelected != value)
{
this.HasChanged = true;
m_fIsSelected = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
修改集合以在删除记录时将 AnyDeleted 属性设置为 true:
protected override void RemoveItem(int index)
{
this.AnyDeleted = true;
base.RemoveItem(index);
}
Run Code Online (Sandbox Code Playgroud)
最后,向集合添加一个方法来指示是否有任何更改。您将调用此方法来确定是否需要保存任何更改:
public bool HasAnyChanges()
{
// Exceptions are handled by the caller
// If anything was deleted, return true
if (this.AnyDeleted)
{
return true;
}
else
{
foreach (T theItem in this)
{
if (theItem.HasAnyChanges())
{
return true;
}
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)