我如何合并两个 Observable 集合,只从新列表中获取新的和更改的项目,并将其添加到旧列表中?

How can I merge two Observable Collections, taking only the new and changed items from the new list, and add it to the old list?

我有一个 WPF 应用程序,它使用绑定到 ObservableCollection 的 DataGrid 元素:

ObservableCollection<Deployment> deployments = DataAccess.GetDeployments();
datagrid01.ItemsSource = deployments;

这是一个部署 class。 Deployment 对象表示现场发生的 Windows 安装,因此像 CurrentTime 这样的东西经常变化。

class Deployment
{
    public string UniqueID { get; set; }        
    public string ComputerName { get; set; }       
    public string IPAddress { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }       
    public string UserName { get; set; }       
    public string TaskSequenceName { get; set; }      
    public string MachineObjectOU { get; set; }
    public DateTime? StartTime { get; set; }
    public DateTime? CurrentTime { get; set; }
    public string Status { get; set; }
}

我想定期用对这些对象的任何更改更新 DataGrid,例如 CurrentTime 或它们的状态。安装完成后状态变为 3,如果处于错误状态则状态变为 2。

所以,我可以在计时器上获得一个新的对象集合,但是仅将这个新集合中的新项目添加到 DataGrid 并更改具有更新时间的现有项目的最佳方法是什么,或状态,或其他什么?

使用 INotifyPropertyChange 界面将 ObservableCollection<Deployment> 设为 属性,将 Raise 设为 property change event。然后,您可以将此 属性 绑定到 xaml 本身中的 DataGriditemsource。因此,您的 collectionUIDatabase 发生的任何变化,整个 list 都会自动刷新。

如下所示的方法应该可以完成这项工作。它不会替换 deployments 集合中的现有项目,而只是更新项目的属性。

为了使 UI 更新,Deployment class 必须实现 INotifyPropertyChanged 接口并在 PropertyChanged 属性 值发生变化。一个简单的解决方案是添加一个 UpdateFrom(Deployment d) 方法,该方法更新所有属性,然后使用 null 作为 属性 名称引发单个 PropertyChanged 事件(以通知所有属性已更改)。

using System.Linq;
...

private void UpdateDeployments(IEnumerable<Deployment> changedDeployments)
{
    foreach (var changedDeployment in changedDeployments)
    {
        var deployment = deployments.FirstOrDefault(
            d => d.UniqueID == changedDeployment.UniqueID);

        if (deployment != null)
        {
            deployment.UpdateFrom(changedDeployment);
        }
        else
        {
            deployments.Add(changedDeployment);
        }
    }
}

使用 .Except() 方法从 ObservableCollection 中过滤项目

newRecordings = recordings.Except(_recordingsHidden).ToList();