我有两个ObservableCollection
通过相互匹配CollectionChanged
事件来监听彼此之间的变化的情况。目标是使两个集合保持同步。
我如何区分
如果我不区分这两者?我想到了暂时的同步过程。但是,这将阻止我在同步(多线程)期间收到有关外部更改的通知。所以我想这一切都可以解决变化的起源问题。
答案 0 :(得分:0)
如果你不反对扩展ObservableCollection类,你可以这样做:
public class SynchronizingCollection<T> : ObservableCollection<T>
{
// the second, synchroniozed collection
SynchronizingCollection<T> _synchronizedCollection;
// field used to determine if the synchronization is already in progress
bool _isSynchronizing = false;
// Methods AddRange, RemoveItems, ReplaceAll, ClearAll
// prevent CollectionChanged event from being rised unnecessarily
// and allow for adding/clearing/replacing items in bulk
public void AddRange(IEnumerable<T> range)
{
if (range == null)
throw new ArgumentNullException("range");
foreach (T item in range)
{
this.Items.Add(item);
}
this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)range.ToList()));
}
public void ReplaceAll(IEnumerable<T> range)
{
if (range == null)
throw new ArgumentNullException("range");
this.Items.Clear();
foreach (T item in range)
{
this.Items.Add(item);
}
this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void RemoveItems(IEnumerable<T> range)
{
if (range == null)
throw new ArgumentNullException("range");
foreach (T item in range)
{
this.Items.Remove(item);
}
this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, (IList)range.ToList()));
}
public void ClearAll()
{
IList old = this.Items.ToList();
base.Items.Clear();
this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, old));
}
// assigning the second collection as synchronized
public void SetSynchronizedCollection(SynchronizingCollection<T> synchronized)
{
this._synchronizedCollection = synchronized;
this._synchronizedCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(_synchronized_CollectionChanged);
this.CollectionChanged += new NotifyCollectionChangedEventHandler(this_CollectionChanged);
}
void this_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_isSynchronizing || _synchronizedCollection==null) return;
_isSynchronizing = true;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
_synchronizedCollection.AddRange(e.NewItems.OfType<T>());
break;
case NotifyCollectionChangedAction.Move:
// implement...
break;
case NotifyCollectionChangedAction.Remove:
_synchronizedCollection.RemoveItems(e.OldItems.OfType<T>());
break;
case NotifyCollectionChangedAction.Replace:
// implement...
break;
case NotifyCollectionChangedAction.Reset:
_synchronizedCollection.ReplaceAll(this.Items);
break;
}
_isSynchronizing = false;
}
void _synchronized_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_isSynchronizing) return;
_isSynchronizing = true;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.AddRange(e.NewItems.OfType<T>());
break;
case NotifyCollectionChangedAction.Move:
// implement...
break;
case NotifyCollectionChangedAction.Remove:
this.RemoveItems(e.OldItems.OfType<T>());
break;
case NotifyCollectionChangedAction.Replace:
// implement...
break;
case NotifyCollectionChangedAction.Reset:
this.ReplaceAll(_synchronizedCollection.Items);
break;
}
_isSynchronizing = false;
}
}
使用代码:
SynchronizingCollection<string> c1 = new SynchronizingCollection<string>();
SynchronizingCollection<string> c2 = new SynchronizingCollection<string>();
c1.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(c1_CollectionChanged);
c2.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(c2_CollectionChanged);
c1.SetSynchronizedCollection(c2);
c1.AddRange(new string[] { "d", "s" });
c1.ClearAll();
c1.Add("a");
c1.Add("b");
c1.Add("c");
c1.Add("d");
c2.Remove("c");
List<string> l = new List<string> { "x1", "x2", "x3", "x4", "x5" };
c2.AddRange(l);
c1.RemoveItems(new string[] { "x2", "b" });
c2.ReplaceAll(l);
//....
void c1_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.Action + " Collection 1 changed");
}
void c2_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.Action + " Collection 2 changed");
}