C# 如何将ObservableCollection作为包装器集合来跟踪更改?
我认为这是一个相当简单的问题,但我仍然找不到更好的解决办法。所以在研究了这个问题之后,我想在这里提出这个问题,以获得专家的意见 基本上,我正在开发WPF应用程序,我已经定义了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>
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);
}
}
}
}