从其他集合更新一个observableCollection

时间:2014-11-14 07:16:18

标签: c# wpf linq observablecollection

我需要从另一个更新一个observablecollection,如下例所示:

使用集合B中的数据更新ObservableCollection A:

ObservableCollection<Category> A = new ObservableCollection<Category>()
{
  new Category()
      {
        ID = 1, 
        Name = ABC
      },
  new Category()
      {
        ID = 4, 
        Name = UVW
      },
  new Category()
      {
        ID = 2, 
        Name = DEF
      },
  new Category()
      {
        ID = 3, 
        Name = XYZ
      }
}

ObservableCollection<Category> B = new ObservableCollection<Category>()
{
  new Category()
      {
        ID = 1, 
        Name = ABC
      },
  new Category()
      {
        ID = 5, 
        Name = LMN
      },
  new Category()
      {
        ID = 7, 
        Name = GHI
      },
  new Category()
      {
        ID = 3, 
        Name = XYZ
      }
}

更新ObservableCollection之后它应该包含与B相同的数据,因为我已将此列表绑定到UI List元素我不希望它清除然后逐个添加所有元素在用户体验中看起来很奇怪。那么是否有任何优化的LINQ可以遍历两个Collection中的所有Elements并使用List B的元素更新List A

1 个答案:

答案 0 :(得分:1)

您可以订阅A的收藏集更改。我在this article的陈述中基于以下实现。我不能确保它完全可操作,因为我不太愿意测试每一个可能的集合操作。

订阅A的更改(实例化后):

A.CollectionChanged += A_CollectionChanged;

B执行同步操作:

private void A_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
            //If index is defined; insert.
            if (e.NewStartingIndex >= 0)
            {
                var index = e.NewStartingIndex;
                foreach (var item in e.NewItems)
                {
                    B.Insert(index, item as Category);
                    index++;
                }
            }
            //Else; add.
            else
                foreach (var item in e.NewItems)
                    B.Add(item as Category);
            break;
        case NotifyCollectionChangedAction.Move:
            //Remove old items at old index first.
            var oldIndex = e.OldStartingIndex;
            for (int i = 0; i < e.OldItems.Count; i++)
            {
                B.RemoveAt(oldIndex);
                oldIndex++;
            }
            //Then add new items at new index.
            var newIndex = e.NewStartingIndex;
            for (int i = 0; i < e.NewItems.Count; i++)
            {
                B.RemoveAt(newIndex);
                newIndex++;
            }
            break;
        case NotifyCollectionChangedAction.Remove:
            //If remove index is defined; remove at index (safe in case item reference appears in collection multiple times)
            if (e.OldStartingIndex >= 0)
            {
                var index = e.OldStartingIndex;
                foreach (var item in e.OldItems)
                {
                    B.RemoveAt(index);
                    index++;
                }
            }
            //Else remove item.
            else
                foreach (var item in e.OldItems)
                    B.Remove(item as Category);
            break;
        case NotifyCollectionChangedAction.Replace:
            //If replace index is defined.
            if (e.NewStartingIndex >= 0)
            {
                var index = e.NewStartingIndex;
                foreach (var item in e.NewItems)
                {
                    B[index] = item as Category;
                    index++;
                }
            }
            //Else try to find index.
            else
                for (int i = 0; i < e.OldItems.Count; i++)
                {
                    var index = B.IndexOf(e.OldItems[i] as Category);
                    B[index] = e.NewItems[i] as Category;
                }
            break;
        case NotifyCollectionChangedAction.Reset:
            //Reset collection.
            B.Clear();
            foreach (var item in sender as ObservableCollection<Category>)
                B.Add(item);
            break;
    }
}