C# 如何确定可观测集合的变化来源
我有这样一个场景:两个C# 如何确定可观测集合的变化来源,c#,collections,C#,Collections,我有这样一个场景:两个observateCollection通过对彼此的CollectionChanged事件进行从属,来监听彼此之间的更改。目标是使两个集合保持同步 我如何区分两者 来自第三方的外部更改,即由于某些代码更改(添加、删除等)其中一个集合,以及 由于同步过程而发生的“内部更改”(即为跟上同步而对其中一个集合进行的更改) 如果我不区分这两者?我暂时想到了同步过程。但是,这将防止我在同步(多线程)期间收到有关外部更改的通知。因此,我想这一切都可以归结为一个问题,即变化起源于何处。如
observateCollection
通过对彼此的CollectionChanged
事件进行从属,来监听彼此之间的更改。目标是使两个集合保持同步
我如何区分两者
- 来自第三方的外部更改,即由于某些代码更改(添加、删除等)其中一个集合,以及
- 由于同步过程而发生的“内部更改”(即为跟上同步而对其中一个集合进行的更改)
如果我不区分这两者?我暂时想到了同步过程。但是,这将防止我在同步(多线程)期间收到有关外部更改的通知。因此,我想这一切都可以归结为一个问题,即变化起源于何处。如果您不反对扩展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;
}
}
公共类同步集合:ObservableCollection
{
//第二,同步收集
同步采集_synchronized采集;
//用于确定同步是否已在进行的字段
bool_isSynchronizing=假;
//方法AddRange、RemoveItems、ReplaceAll、ClearAll
//防止不必要地引发CollectionChanged事件
//并允许批量添加/清除/更换项目
public void AddRange(IEnumerable range)
{
如果(范围==null)
抛出新的ArgumentNullException(“范围”);
foreach(范围内的T项)
{
此.Items.Add(item);
}
此.OnPropertyChanged(新PropertyChangedEventArgs(“计数”);
此.OnPropertyChanged(新的PropertyChangedEventArgs(“项目[]”);
this.OnCollectionChanged(新的NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,(IList)range.ToList());
}
公共void ReplaceAll(IEnumerable范围)
{
如果(范围==null)
抛出新的ArgumentNullException(“范围”);
this.Items.Clear();
foreach(范围内的T项)
{
此.Items.Add(item);
}
此.OnPropertyChanged(新PropertyChangedEventArgs(“计数”);
此.OnPropertyChanged(新的PropertyChangedEventArgs(“项目[]”);
this.OnCollectionChanged(新建NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
公共无效删除项(IEnumerable range)
{
如果(范围==null)
抛出新的ArgumentNullException(“范围”);
foreach(范围内的T项)
{
此。项。删除(项);
}
此.OnPropertyChanged(新PropertyChangedEventArgs(“计数”);
此.OnPropertyChanged(新的PropertyChangedEventArgs(“项目[]”);
this.OnCollectionChanged(新的notifyCollectionChangedEntargs(NotifyCollectionChangedAction.Remove,(IList)range.ToList());
}
公共无效ClearAll()
{
IList old=this.Items.ToList();
base.Items.Clear();
此.OnPropertyChanged(新PropertyChangedEventArgs(“计数”);
此.OnPropertyChanged(新的PropertyChangedEventArgs(“项目[]”);
this.OnCollectionChanged(新建NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,old));
}
//将第二个集合指定为已同步
public void SetSynchronizedCollection(SynchronizingCollection已同步)
{
此。_synchronizedCollection=已同步;
此.\u synchronizedCollection.CollectionChanged+=新的NotifyCollectionChangedEventHandler(\u synchronized\u CollectionChanged);
this.CollectionChanged+=新的NotifyCollectionChangedEventHandler(this\u CollectionChanged);
}
作废此\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
if(_isSynchronizing | | | u synchronizedCollection==null)返回;
_isSynchronizing=true;
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
_synchronizedCollection.AddRange(例如NewItems.OfType());
打破
案例通知收集更改操作。移动:
//实施。。。
打破
案例NotifyCollectionChangedAction。删除:
_synchronizedCollection.RemoveItems(例如OldItems.OfType());
打破
案例通知收集更改操作。替换:
//实施。。。
打破
案例通知CollectionChangedAction.Reset:
_synchronizedCollection.ReplaceAll(此.Items);
打破
}
_isSynchronizing=错误;
}
void\u synchronized\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
如果(_isSynchronizing)返回;
_isSynchronizing=true;
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
this.AddRange(例如NewItems.OfType());
打破
案例通知收集更改操作。移动:
//实施。。。
打破
案例NotifyCollectionChangedAction。删除:
this.removitems(例如OldItems.OfType());
打破
案例通知收集更改操作。替换:
//实施。。。
打破
案例通知CollectionChangedAction.Reset:
this.ReplaceAll(_synchronizedCollection.Items);
打破
}
_isSynchronizing=错误;
}
}
使用代码:
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");
}
SynchronizingCollection c1=新的SynchronizingCollection();
SynchronizingCollection c2=新的SynchronizingCollection();
c1.CollectionChanged+=新系统.Collections.Specialized.NotifyCollectionChangedEventHandler(c1\U CollectionChanged);
c2.CollectionChanged+=新系统.Collections.Specialized.NotifyCollectionChan