.net 锁定/解锁可观察采集<;T>;
我需要允许或防止修改.net 锁定/解锁可观察采集<;T>;,.net,observablecollection,.net,Observablecollection,我需要允许或防止修改ObservableCollection(或者至少是实现WPF绑定的INotifyCollectionChanged的类型)以及它所包含的基于业务规则的对象 我可以解决防止修改包含的对象的问题,但不确定如何防止更改集合本身。一种选择是订阅CollectionChanged事件,并在更改发生后撤消更改,但这并不优雅,对客户来说是一个令人困惑的契约 还有哪些其他方法?您可以创建自己的集合类型并继承可观测集合。这是一个潜在的选择吗 public class ReadOnlyObse
ObservableCollection
(或者至少是实现WPF绑定的INotifyCollectionChanged
的类型)以及它所包含的基于业务规则的对象
我可以解决防止修改包含的对象的问题,但不确定如何防止更改集合本身。一种选择是订阅CollectionChanged
事件,并在更改发生后撤消更改,但这并不优雅,对客户来说是一个令人困惑的契约
还有哪些其他方法?您可以创建自己的集合类型并继承
可观测集合。这是一个潜在的选择吗
public class ReadOnlyObservableCollection<T> : ObservableCollection<T>
{
// method overrides with conditional logic to allow/deny changes
}
公共类ReadOnlyObservableCollection:ObservableCollection
{
//方法用条件逻辑重写以允许/拒绝更改
}
您可以声明自己实现ICollection(和friends)接口的类,并使基础集合成为该类的成员。您不希望继承,因为这样可能会有人简单地将对象引用强制转换为基类,而您已经失去了保护
在正常情况下,将所有更新委托给基础类,直到集合被锁定。当它被锁定时,开始抛出断言,而不是转发下面的调用。并且所有读取操作都始终被委派
这基本上是我同意建议包装一个
可观察集合
。这是我的实现,以防对任何人有所帮助。这种方法的一个缺点是所包含对象上的ILockable.Locked是公共的,因此可以解锁单个包含的对象,如:wrappedCollection.Item(0).Locked=false代码>。此外,我还没有实现索引器,因为EF。如果您不使用EF,请随意添加索引器
public interface ILockable
{
bool Locked { get; set; }
}
public class LockableObservableCollection<T> : ICollection<T>, INotifyCollectionChanged, INotifyPropertyChanged, ILockable
where T: ILockable
{
protected ObservableCollection<T> Collection { get; set; }
public LockableObservableCollection()
{
Collection = new ObservableCollection<T>();
Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
((INotifyPropertyChanged)Collection).PropertyChanged +=
new PropertyChangedEventHandler(LockableObservableCollection_PropertyChanged);
}
void LockableObservableCollection_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null) PropertyChanged(this, e);
}
void Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null) CollectionChanged(this, e);
}
public T Item(int index)
{
return Collection[index];
}
#region ICollection<T>
public void Add(T item)
{
if (Locked) throw new Exception("Collection is locked.");
Collection.Add(item);
}
public void Clear()
{
if (Locked) throw new Exception("Collection is locked.");
Collection.Clear();
}
public bool Contains(T item)
{
return Collection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
Collection.CopyTo(array, arrayIndex);
}
public int Count
{
get { return Collection.Count; }
}
public bool IsReadOnly
{
get { return Locked; }
}
public bool Remove(T item)
{
if (Locked) throw new Exception("Collection is locked.");
bool result = Collection.Remove(item);
return result;
}
public IEnumerator<T> GetEnumerator()
{
return Collection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region INotifyCollectionChanged
public event NotifyCollectionChangedEventHandler CollectionChanged;
#endregion
#region IPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private bool locked;
public bool Locked
{
get
{
return locked;
}
set
{
if (locked != value)
{
locked = value;
foreach (T t in Collection)
{
t.Locked = value;
}
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Locked"));
}
}
}
}
}
private string text;
public string Text
{
get { return text; }
set
{
if (text != value)
{
if (Locked) throw new Exception("This item is locked to prevent changes.");
text = value;
}
}
}