比较两个ObservableCollection(s),看它们是否不同

本文关键字:是否 两个 ObservableCollection 比较 | 更新日期: 2023-09-27 18:19:21

我正在比较listview的两个版本,用于设置表单。我需要知道用户是否真的修改了列表,在这种情况下,当他们点击"保存"时,我就会保存。如果他们没有更改任何内容,当他们点击"保存"时,我就不会浪费内存/时间重新保存他们没有更改的内容。

无论如何,我如何比较两个observablecollection来查看它们是否完全不同?

提前感谢!

比较两个ObservableCollection(s),看它们是否不同

您可以使用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
    }
}

在第一个集合上调用Except方法,并将第二个集合作为参数传递。结果将包含差异。然后,您可以查询结果并采取相应的操作。如果两个序列相等,则结果计数为0。

话虽如此,值得注意的是,在MVVM世界中,首选策略是使用此方法来控制是否启用"保存"按钮。在这种方法中,如果两个集合相等,"Save"按钮将被禁用,用户无法访问它。

但无论哪种方式,LINQ方法都提供了一种非常简洁的方式来实现你所追求的…

补充:看到你在回复'Dumb'的评论中所做的评论,你的'oldList'将对应于上面示例代码中的numbersB…


还有来自'Stonetip'的评论(感谢他)…

More succinct: if(numbersA.Except(numbersB).Any()) { // do something } 

我们处理这个问题的方式需要预先多做一点工作,但它可以使用VS宏或代码生成工具(如codessmith)自动完成。

但是,这种方法可以扩展到集合绑定到的任何UI构造,并且不必在每次需要知道是否有更改时都在UI中重新实现。

这个概念是更新集合和业务对象中的标志,以确定集合成员是否已更改,或者集合内的任何给定记录是否已更改。

实现相当简单:

为业务对象类添加一个HasChanged属性。

向集合添加AnyDeleted属性。只有当项从集合中删除时才会设置。

在从DB读取记录后将这些值初始化为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;
    }

我认为,你关注的方法是错误的。您不应该比较绑定到ListView的两个列表的内容,因为它们包含的项目数量可能非常大。

  • 最好是专注于定义一个单一的(如果可能的话)和统一的方式来从API改变集合的内容,为你的类消费者提供一个通用的方式来改变集合中的一些东西。如果使用该方法,则可以保存一个布尔值flag,该值标识是否发生了更改。

  • 或者你可以假设,如果有人在绑定的集合属性中使用set方法,意味着集合被改变了。

换句话说,传递应用程序的预定义工作流,或者定义用于更改内容的API,这样您就能够在更改集合的内容时确定,如果更改则确定

和另一个概念:没有意义让用户点击Save不保存。如果可以单击Save,则必须执行用户请求的命令。如果你担心性能(你不想保存一些东西,如果它没有从上次保存更改),那么禁用Save按钮,如果保存不合适。换句话说,让UI填充并按照应用程序的预期行事。让用户清楚应用程序现在做什么,不做什么。