Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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# 如何将ObservableCollection作为包装器集合来跟踪更改?_C#_Wpf_Entity Framework_Observablecollection_Custom Collection - Fatal编程技术网

C# 如何将ObservableCollection作为包装器集合来跟踪更改?

C# 如何将ObservableCollection作为包装器集合来跟踪更改?,c#,wpf,entity-framework,observablecollection,custom-collection,C#,Wpf,Entity Framework,Observablecollection,Custom Collection,我认为这是一个相当简单的问题,但我仍然找不到更好的解决办法。所以在研究了这个问题之后,我想在这里提出这个问题,以获得专家的意见 基本上,我正在开发WPF应用程序,我已经定义了GenericObserableCollection实现observedcollection,并且大多数集合都实现了它,以便在整个项目中使用标准方法 [Serializable] [CollectionDataContract] public class GenericObservableCollection<T>

我认为这是一个相当简单的问题,但我仍然找不到更好的解决办法。所以在研究了这个问题之后,我想在这里提出这个问题,以获得专家的意见

基本上,我正在开发WPF应用程序,我已经定义了
GenericObserableCollection
实现
observedcollection
,并且大多数集合都实现了它,以便在整个项目中使用标准方法

[Serializable]
[CollectionDataContract]
public class GenericObservableCollection<T> : ObservableCollection<T>
{
        public GenericObservableCollection() { }
        public GenericObservableCollection(IEnumerable<T> collection)
            : base(collection) { }
}

[Serializable]
[CollectionDataContract]
public class GenericRuleCollection : GenericObservableCollection<IRule>
{
        public GenericRuleCollection() { }
        public GenericRuleCollection(IEnumerable<IRule> collection) 
            : base(collection) { }
}

我不认为我完全理解您的要求,但当您将“更改跟踪集合”作为集合包装器时,这个可能适合您。我目前正在用它来完成我的最终学位项目。我在结尾放了一个链接

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;

namespace Core
{
    public interface IValidatableTrackingObject :
        IRevertibleChangeTracking, 
        INotifyPropertyChanged
    {
        bool IsValid { get; }
    }

    public class ChangeTrackingCollection<T> : ObservableCollection<T>, IValidatableTrackingObject
        where T : class, IValidatableTrackingObject
    {
        private IList<T> _originalCollection;

        private ObservableCollection<T> _addedItems;
        private ObservableCollection<T> _removedItems;
        private ObservableCollection<T> _modifiedItems;

        public ChangeTrackingCollection(IEnumerable<T> items)
            : base(items)
        {
            _originalCollection = this.ToList();

            AttachItemPropertyChangedHandler(_originalCollection);

            _addedItems = new ObservableCollection<T>();
            _removedItems = new ObservableCollection<T>();
            _modifiedItems = new ObservableCollection<T>();

            this.AddedItems = new ReadOnlyObservableCollection<T>(_addedItems);
            this.RemovedItems = new ReadOnlyObservableCollection<T>(_removedItems);
            this.ModifiedItems = new ReadOnlyObservableCollection<T>(_modifiedItems);
        }

        public ReadOnlyObservableCollection<T> AddedItems { get; private set; }
        public ReadOnlyObservableCollection<T> RemovedItems { get; private set; }
        public ReadOnlyObservableCollection<T> ModifiedItems { get; private set; }

        public bool IsChanged => AddedItems.Count > 0
                                || RemovedItems.Count > 0
                                || ModifiedItems.Count > 0;

        public bool IsValid => this.All(t => t.IsValid);

        public void AcceptChanges()
        {
            _addedItems.Clear();
            _removedItems.Clear();
            _modifiedItems.Clear();
            foreach (var item in this)
            {
                item.AcceptChanges();
            }

            _originalCollection = this.ToList();
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
        }

        public void RejectChanges()
        {
            foreach (var removedItem in _removedItems.ToList()) this.Add(removedItem);
            foreach (var addedItem in _addedItems.ToList()) this.Remove(addedItem);
            foreach (var modifiedItem in _modifiedItems.ToList()) modifiedItem.RejectChanges();

            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
        }

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            var added = this.Where(current => _originalCollection.All(orig => orig != current));
            var removed = _originalCollection.Where(orig => this.All(current => current != orig));

            var modified = this.Except(added).Except(removed).Where(item => item.IsChanged).ToList();

            AttachItemPropertyChangedHandler(added);
            DetachItemPropertyChangedHandler(removed);

            UpdateObservableCollection(_addedItems, added);
            UpdateObservableCollection(_removedItems, removed);
            UpdateObservableCollection(_modifiedItems, modified);

            base.OnCollectionChanged(e);
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsValid)));
        }

        private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(IsValid))
            {
                OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsValid)));
            }
            else
            {
                var item = (T)sender;
                if (_addedItems.Contains(item))
                {
                    return;
                }

                if (item.IsChanged)
                {
                    if (!_modifiedItems.Contains(item))
                    {
                        _modifiedItems.Add(item);
                    }
                }
                else
                {
                    if (_modifiedItems.Contains(item))
                    {
                        _modifiedItems.Remove(item);
                    }
                }

                OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
            }
        }

        private void AttachItemPropertyChangedHandler(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                item.PropertyChanged += ItemPropertyChanged;
            }
        }

        private void DetachItemPropertyChangedHandler(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                item.PropertyChanged -= ItemPropertyChanged;
            }
        }

        private void UpdateObservableCollection(ObservableCollection<T> collection, IEnumerable<T> items)
        {
            collection.Clear();
            foreach (var item in items)
            {
                collection.Add(item);
            }
        }
    }
}
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Collections.Specialized;
使用系统组件模型;
使用System.Linq;
名称空间核心
{
公共接口IValidatableTrackingObject:
IRevertibleChangeTracking,
InotifyProperty已更改
{
bool是有效的{get;}
}
公共类ChangeTrackingCollection:ObservableCollection,IValidatableTrackingObject
其中T:类,IValidatableTrackingObject
{
私人IList_原始集合;
私有可观测集合_addedItems;
私人可观察到的回收项目;
私有可观测集合_modifiedItems;
公共ChangeTrackingCollection(IEnumerable项)
:基本(项目)
{
_originalCollection=this.ToList();
附件属性更改句柄(原始集合);
_addedItems=新的ObservableCollection();
_removedItems=新的ObservableCollection();
_modifiedItems=新的ObservableCollection();
this.AddedItems=新的ReadOnlyObservableCollection(_AddedItems);
this.RemovedItems=新的ReadOnlyObservableCollection(\u RemovedItems);
this.ModifiedItems=新的ReadOnlyObservableCollection(\u ModifiedItems);
}
public ReadOnlyObservableCollection AddedItems{get;private set;}
public ReadOnlyObservableCollection RemovedItems{get;private set;}
public ReadOnlyObservableCollection ModifiedItems{get;private set;}
public bool IsChanged=>AddedItems.Count>0
||RemovedItems。计数>0
||ModifiedItems.Count>0;
public bool IsValid=>this.All(t=>t.IsValid);
公共更改()
{
_addedItems.Clear();
_removedItems.Clear();
_modifiedItems.Clear();
foreach(本文件中的var项目)
{
item.AcceptChanges();
}
_originalCollection=this.ToList();
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsChanged));
}
公共更改()
{
foreach(var removedItem在_removedItems.ToList()中)this.Add(removedItem);
foreach(var addedItem in_addedItems.ToList())this.Remove(addedItem);
foreach(在_modifiedItems.ToList()中的var modifiedItem)modifiedItem.RejectChanges();
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsChanged));
}
CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
{
var added=this.Where(当前=>_originalCollection.All(原始=>原始!=当前));
var removed=_originalCollection.Where(orig=>this.All(current=>current!=orig));
var modified=this.Except(added).Except(removed).Where(item=>item.IsChanged).ToList();
附件不动产变更处理程序(新增);
DetachItemPropertyChangedHandler(已删除);
UpdateObservableCollection(_addedItems,added);
UpdateObservableCollection(\u removedItems,removed);
UpdateObservableCollection(_modifiedItems,modified);
基础。变更的集合(e);
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsChanged));
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsValid));
}
私有void ItemPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
如果(e.PropertyName==nameof(IsValid))
{
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsValid));
}
其他的
{
变量项=(T)发送方;
如果(_addedItems.Contains(项目))
{
返回;
}
如果(项目已更改)
{
如果(!\u modifiedItems.包含(项目))
{
_修改项目。添加(项目);
}
}
其他的
{
如果(_modifiedItems.Contains(项目))
{
_修改后的项目。删除(项目);
}
}
OnPropertyChanged(新PropertyChangedEventArgs(nameof(IsChanged));
}
}
私有void AttachItemPropertyChangedHandler(IEnumerable items)
{
foreach(项目中的var项目)
{
item.PropertyChanged+=ItemPropertyChanged;
}
}
私有void DetachItemPropertyChangedHandler(IEnumerable items)
{
foreach(项目中的var项目)
{
item.PropertyChanged-=ItemPropertyChanged;
}
}
私有void UpdateObservableCollection(ObservableCollection集合,IEnumerable项)
{
collection.Clear();
foreach(项目中的var项目)
{
集合。添加(项目);
}
}
}
}

但您的常规可观察收藏
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;

namespace Core
{
    public interface IValidatableTrackingObject :
        IRevertibleChangeTracking, 
        INotifyPropertyChanged
    {
        bool IsValid { get; }
    }

    public class ChangeTrackingCollection<T> : ObservableCollection<T>, IValidatableTrackingObject
        where T : class, IValidatableTrackingObject
    {
        private IList<T> _originalCollection;

        private ObservableCollection<T> _addedItems;
        private ObservableCollection<T> _removedItems;
        private ObservableCollection<T> _modifiedItems;

        public ChangeTrackingCollection(IEnumerable<T> items)
            : base(items)
        {
            _originalCollection = this.ToList();

            AttachItemPropertyChangedHandler(_originalCollection);

            _addedItems = new ObservableCollection<T>();
            _removedItems = new ObservableCollection<T>();
            _modifiedItems = new ObservableCollection<T>();

            this.AddedItems = new ReadOnlyObservableCollection<T>(_addedItems);
            this.RemovedItems = new ReadOnlyObservableCollection<T>(_removedItems);
            this.ModifiedItems = new ReadOnlyObservableCollection<T>(_modifiedItems);
        }

        public ReadOnlyObservableCollection<T> AddedItems { get; private set; }
        public ReadOnlyObservableCollection<T> RemovedItems { get; private set; }
        public ReadOnlyObservableCollection<T> ModifiedItems { get; private set; }

        public bool IsChanged => AddedItems.Count > 0
                                || RemovedItems.Count > 0
                                || ModifiedItems.Count > 0;

        public bool IsValid => this.All(t => t.IsValid);

        public void AcceptChanges()
        {
            _addedItems.Clear();
            _removedItems.Clear();
            _modifiedItems.Clear();
            foreach (var item in this)
            {
                item.AcceptChanges();
            }

            _originalCollection = this.ToList();
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
        }

        public void RejectChanges()
        {
            foreach (var removedItem in _removedItems.ToList()) this.Add(removedItem);
            foreach (var addedItem in _addedItems.ToList()) this.Remove(addedItem);
            foreach (var modifiedItem in _modifiedItems.ToList()) modifiedItem.RejectChanges();

            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
        }

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            var added = this.Where(current => _originalCollection.All(orig => orig != current));
            var removed = _originalCollection.Where(orig => this.All(current => current != orig));

            var modified = this.Except(added).Except(removed).Where(item => item.IsChanged).ToList();

            AttachItemPropertyChangedHandler(added);
            DetachItemPropertyChangedHandler(removed);

            UpdateObservableCollection(_addedItems, added);
            UpdateObservableCollection(_removedItems, removed);
            UpdateObservableCollection(_modifiedItems, modified);

            base.OnCollectionChanged(e);
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsValid)));
        }

        private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(IsValid))
            {
                OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsValid)));
            }
            else
            {
                var item = (T)sender;
                if (_addedItems.Contains(item))
                {
                    return;
                }

                if (item.IsChanged)
                {
                    if (!_modifiedItems.Contains(item))
                    {
                        _modifiedItems.Add(item);
                    }
                }
                else
                {
                    if (_modifiedItems.Contains(item))
                    {
                        _modifiedItems.Remove(item);
                    }
                }

                OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsChanged)));
            }
        }

        private void AttachItemPropertyChangedHandler(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                item.PropertyChanged += ItemPropertyChanged;
            }
        }

        private void DetachItemPropertyChangedHandler(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                item.PropertyChanged -= ItemPropertyChanged;
            }
        }

        private void UpdateObservableCollection(ObservableCollection<T> collection, IEnumerable<T> items)
        {
            collection.Clear();
            foreach (var item in items)
            {
                collection.Add(item);
            }
        }
    }
}