Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何确定可观测集合的变化来源_C#_Collections - Fatal编程技术网

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