比较两个ObservableCollection(s)以查看它们是否不同
我正在比较设置表单的两个版本的listview。我需要知道用户是否真的修改了列表,在这种情况下,当他们点击“保存”时,我将实际保存。如果他们没有改变任何东西,当他们点击“保存”时,我不会浪费记忆/时间重新保存他们没有改变的东西。比较两个ObservableCollection(s)以查看它们是否不同
无论如何,我怎么能比较两个ObservableCollections,看看他们是否有所不同?
在此先感谢!
我们处理这个问题的方式需要多一点工作,但可以使用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;
}
}
}
修改收集到AnyDeleted属性设置为true,当一条记录被删除:
protected override void RemoveItem(int index)
{
this.AnyDeleted = true;
base.RemoveItem(index);
}
最后一个方法添加到集合,表示什么是否已经改变。这是您要调用以确定是否需要保存任何更改的方法:
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;
}
编辑:
void ListView_ItemInserted(Object sender, ListViewInsertedEventArgs e)
{
if (e.Exception == null)
{
if (e.AffectedRows > 0)
{
flag = True;
}
else
{
flag = False;
}
}
void ListView_Itemdeleted(Object sender, ListViewDeletedEventArgs e)
{
if (e.Exception == null)
{
if (e.AffectedRows > 0)
{
flag = True;
}
else
{
flag = False;
}
}
void ListView_ItemUpdated(Object sender, ListViewUpdatedEventArgs e)
{
if (e.Exception == null)
{
if (e.AffectedRows > 0)
{
flag = True;
}
else
{
flag = False;
}
}
可以在保存前检查此标志变量。这会做!如果它是真的,保存它!
您可以使用LINQ Except方法:生成两个序列的集合差异。
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
}
}
的除方法被调用在所述第一收集和通过了第二集合作为参数。结果将包含差异。然后,您可以查询结果并相应采取行动。如果两个序列相等,则结果的计数将为零。
话虽如此,值得一提的是,MVVM世界中的首选策略是使用此方法来控制是否启用“保存”按钮。在这种方法中,如果两个集合相同,则“保存”按钮将被禁用,用户将无法访问它。
但无论哪种方式,LINQ方法提供实现你追求的一个很浓缩的方式...
补充说:看到你在回答“哑的”意见所提出的意见,你的“oldList”会对应于在numbersB上面的示例代码...
另外,从comment '3210'(对谁感谢)...
More succinct: if(numbersA.Except(numbersB).Any()) { // do something }
我认为这些词很容易混淆,并且“oldList仅仅是旧列表(用户改变它们之前的当前设置)”意味着他可能会说已经保存到设置中,而当前列表意味着不保存。他可能没有两个集合,但已经保存了一个(他将它虚拟成一个集合),另一个集合在列表视图上。如果他在内存中同时拥有两个集合,那么除了LINQ的方法之外,它还是很好用的。使用LINQ(简明方法)+1。让我们听听他关于他作品的更多描述。 – King 2012-01-01 14:59:50
@哑,嗨,新年快乐!您是否可以使用'编辑'功能来修改令人困惑的部分,以便清楚?你是否意味着这些设置并不意味着持久? – 2012-01-01 15:10:06
新年快乐!我正在等待他澄清一点,以便我们能够确切了解他需要什么,并且我们可以编辑这些内容。是。我认为他的数据不是持久的。但是,当然有两个版本与他在评论中所说的内容不一致。所以他希望每次使用listview检查时都检查一下,这就是为什么我建议检查listview方法的事件。但是如果他有两个版本的持久数据,我会推荐使用你的方法! – King 2012-01-01 15:27:54
我个墨水,你正在关注错误的方法。您不应该将绑定到ListView
的2个列表的内容进行比较,因为它们包含的项目数量可能过大。
这是更好地专注于制定一个统一(这是可能的)和统一的方式能够改变的集合来自API的内容,提供给您的消费阶层的一般方法,以能够改变收藏中的东西。如果使用该方法,您可以保存一个布尔值
flag
,用于标识是否更改了某些内容。或者你可以假设,如果有人在绑定收集属性中使用
set
方法,意味着集合已被更改。
换句话说,继电器或您的应用程序的预定义的工作流程,或改变内容的定义API
,这样你就可以找出当和如果集合的内容被改变。
还有一个概念:没有意义让用户点击Save
和不保存。如果可以点击Save
,则必须执行用户请求的命令。如果您对性能保持警惕(如果不想保存某些内容,如果不是上次保存的更改),请在保存不合适的情况下禁用Save
按钮。换句话说,使用UI
填充并按照您的应用程序的预期运行。让用户清楚现在应该做什么以及不做什么。
没有两个列表视图,实际上只有一个。 – mattsven 2012-01-01 00:26:12
你的问题表明有两个版本的listviews! 那么你的意思是?你再次提到过比较两个! – King 2012-01-01 00:31:29
你正在绑定一个像XML一样的数据结构或将它作为字符串,然后将其保存在设置?是这样吗 ? @NeXXeuS如果我理解你的问题是这样的。然后,除非应用程序具有内存中的设置并不断更新它,否则您必须阅读设置并执行此操作。它和拯救它一样。如果事实如此,我认为它不会在性能方面产生影响。 – King 2012-01-01 00:37:39