比较两个 ObservableCollection 以查看它们是否不同

发布于 2024-12-24 19:15:41 字数 209 浏览 0 评论 0原文

我正在研究比较两个版本的列表视图的设置表单。我需要知道用户是否真的修改了列表,在这种情况下,当他们单击“保存”时,我实际上会保存。如果他们没有更改任何内容,当他们单击“保存”时,我不会浪费内存/时间来重新保存他们没有更改的内容。

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

提前致谢!

I'm working on comparing two versions of a listview, for a settings form. I need to know if the user actually modified the list at all, in which case when they click "Save" I'll actually save. If they didn't change anything, when they click "Save" I won't be wasting memory/time re-saving something they didn't change.

Anyway, how can I compare two ObservableCollections to see if they are at all different?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

定格我的天空 2024-12-31 19:15:41

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

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

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

添加:看到您在回复“Dumb's”评论时所做的评论,您的“oldList”将对应于上面示例代码中的numbersB ...


还有来自'Stonetip'(给谁 谢谢)...

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

You can use the LINQ Except method: Produces the set difference of two sequences.

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except.aspx

Consider the following sample method...

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
    }
}

The Except method is invoked on the first collection and passed the second collection as an argument. The result will contain the differences. You can then query the result and take action accordingly. If both sequences are equal, the result's count will be zero.

Having said that, it's worthy to note that the preferred strategy in the MVVM world would be to use this method to control whether or not your 'Save' button is enabled. In this approach, if the two collections are equal, the 'Save' button would be disabled and the user could not access it.

But either way, the LINQ method offers a very condensed way of achieving what you're after...

ADDING: seeing the comments you made in reply to 'Dumb's' comment, your 'oldList' would correspond to numbersB in the sample code above...


Also the comment from 'Stonetip' (to whom thanks)...

More succinct: if(numbersA.Except(numbersB).Any()) { // do something } 
攒眉千度 2024-12-31 19:15:41

我们处理这个问题的方式需要预先做更多的工作,但可以使用 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;
    }

The way that we handle this requires a little more work up front, but it can be automated using VS macros or code-gen tools such as CodeSmith.

However, this approach is extensible to any UI construct that the collection is bound to and doesn't have to be re-implemented in the UI each time you need to know whether there are changes or not.

The concept is to update flags within the collection and business object to determine whether or not the collection membership has changed or any given record has changed within the collection.

The implementation is fairly simple:

Add a HasChanged property to the business object class.

Add an AnyDeleted property to the collection. This will only be set if items are deleted from the collection.

Initialize these values to false after the records are read from the DB.

(Now the semi-tedious part) For each property in the class, set the HasChanged property to true if the value actually changes. Be careful of null values. For example:

    public bool IsSelected
    {
        get
        {
            return m_fIsSelected;
        }
        set
        {
            if (m_fIsSelected != value)
            {
                this.HasChanged = true;
                m_fIsSelected = value;
            }
        }
    }

Modify the collection to set the AnyDeleted property to true when a record is deleted:

    protected override void RemoveItem(int index)
    {
        this.AnyDeleted = true;

        base.RemoveItem(index);
    }

Finally, add a method to the collection to indicate whether or not anything has changed. This is the method that you will call to determine whether or not any changes need to be saved:

   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;
    }
月隐月明月朦胧 2024-12-31 19:15:41

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

  • 最好专注于定义一个单一的(如果可能的话)和统一的方法,以便能够通过 API 更改集合的内容,为您的类使用者提供一种能够更改集合中某些内容的通用方法。如果使用该方法,您可以保存一个布尔标志来标识某些内容是否发生了更改。

  • 或者您可以假设,如果有人在绑定的集合属性中使用 set 方法,则意味着集合已更改。

换句话说,中继或应用程序的预定义工作流程,或定义用于更改内容的API,以便您能够确定何时如果< /em> 集合的内容已更改。

还有另一个概念:让用户单击保存并且不保存是没有意义的。如果可以单击“保存”,则必须执行用户请求的命令。如果您对性能持谨慎态度(您不想保存某些内容,如果它与上次保存相比没有更改),那么如果保存不合适,请禁用保存按钮。换句话说,让 UI 填充并按照应用程序的预期运行。让用户清楚应用程序现在做什么和不做什么。

I think, you are focusing on the wrong approach. You shouldn't compare the content of 2 lists binded to a ListView, also because the quantity of items they contain can be prohibitively large.

  • It's better to focus on defining a single (if this is possible) and uniform way to be able to change the content of a collection from the API, providing to your class consumer a general way to be able to change something in collection. If that method is used, you can hold a boolean flag that identifies if something was changed.

  • Or you can suppose, that if someone uses set method inside binded collection property, means the collection was changed.

In other words, relay or on predefined workflow of your application, or define an API for changing content, so you will be able to figure out when and if the content of the collections was changed.

And another notion yet: there is no sense to let to the user click Save and do not save. If it's possible to click Save the command requested by the user has to be executed. If you are wary about performance (you don't want to save something, if it wasn't change from last save), so disable the Save button, if the save is not appropriate. In other words, make a UI fill and behave as it expected by your app. Making to the user clear what app does now and what it does not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文