控制从ObservableCollection派生的类中元素的可访问性 [英] Control accessability of elements in a class derived from ObservableCollection
问题描述
大家好,
我只是在讨论一些想法,想知道是否可以在没有太多麻烦的情况下进行以下操作...
想象一个像这样的课程:
Hi all,
I am just playing around with some ideas and was wondering if the following would be possible without too much hassle...
Imagine a class like this:
public class Animals : ObservableCollection<Animal>
{
}
当然,这个极其罕见的课程
And of course this radically rare class
public class Animal
{
public string Name{ get; set; }
public bool IsAlive{ get; set; }
public bool Buried{ get; set; }
}
现在,如果有人使用Animals
类,那么他/她可能对检索那些还没有生命和被掩埋的动物不感兴趣(如果需要的话,我可以提供一个功能来获取这些动物).
那么是否可以通过某种方式修改Animals
类,使其仅考虑实际存在且未隐藏的Animal
实例?
因此,在Animal
实例实际上被掩埋之后(当然不再是活的-如果被掩埋活着,它可能会自动更改),因此应该不再使用Animals
类的标准检索方法(也包括Count和Linq)来提供它相关的内容,例如第一",位置"等-您可以看到图片.
到目前为止,我已经在Animal
类中实现了INotifyPropertyChanged
接口,以允许Animals
删除那些实例(死的和埋藏的)并在内部存储它们,效果很好.但是,是否有解决该问题的更优雅的方法?
更新:
也许我可以再简化一点.
是否有可能以某种方式修改Animals
类以仅返回Animal
的实例,而其中的实例不返回(Alive = false AND Buried = true),以使它们不再被外界看到,而是将其保留在列表中?
可以通过如下方式覆盖/覆盖枚举器来进行Mabe:
Now if someone uses the Animals
class he/she would propably not be interested in retrieving animals that are not alive and buried (if so I could provide a function to get these if neccessary).
So would it somehow be possible to modify the Animals
class so that it only respects instances of Animal
that are actually alive and not buried?
So after an instance of Animal
is actually buried (and of course no longer alive - which might automatically change if buried alive) it should not be available anymore by using the standard retrieval methods of the Animals
class (also Count and Linq related stuff like First, Where, etc. - you get the picture).
So far I implemented the INotifyPropertyChanged
interface in the Animal
class to allow Animals
to remove those instances (dead and buried) and store them internally, which works fine. But would there be a more elegant solution to the problem?
UPDATE:
Maybe I can simplify it a little bit more.
Would it be possible to modify the Animals
class somehow to only return instances of Animal
where not (Alive = false AND Buried = true) so that they can no longer be seen by the outside world but to keep it in the list?
Mabe by overriding/overwriting the enumerator like this:
new public IEnumerator GetEnumerator()
{
IEnumerator ie = base.GetEnumerator();
while (ie.MoveNext())
{
Animal animal = (Animal)ie.Current;
if(animal.Alive && !animal.Buried)
yield return ie.Current;
}
}
..但是这还会影响列表的Count,First等吗?
更新:
我发现以上内容会影响foreach(可以预见),但不会影响Count或Linq方法...
我在这里很难用英语表达自己,请保持怜悯:)
任何想法都表示赞赏,
祝你有美好的一天
Andy
..but would that also affect Count, First, etc of the List?
UPDATE:
I figured out that the above will affect foreach (which was ecpectable) but not Count or Linq methods...
I have hard time expressing myself in english here, please be mercyfull :)
Any thoughts are kindly appreciated,
have a great day
Andy
推荐答案
首先感谢Malli_S,Kenneth Haugland和Ashraff Ali Wahab的贡献.非常感谢!!!
最后,我提出了以下解决方案,解决了我的问题.
如果有人对此发表评论,我将非常有兴趣听到它.
我只发布了ObservableCollection的替换项,因为涉及的很多东西超出了问题的范围.
First of all thanks to Malli_S, Kenneth Haugland and Ashraff Ali Wahab for their contribution. It is very much appreciated!!!
In the end I came up with the following, which solves my problem.
If anybody has a comment on this I would be interested very much in hearing about it.
I only posted the replacement for the ObservableCollection because there is quite a bunch of stuff involved that would be out of the scope of the question.
public abstract class BuryableBaseClassObservableCollection<T> : ObservableCollection<T>, ITransactionEnabled where T : BuryableBaseClass
{
protected BuryableBaseClassObservableCollection()
{
InitializeInternalEvents();
}
protected void InitializeInternalEvents()
{
this.CollectionChanged += ItemsBaseCollectionChanged;
}
void ItemsBaseCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
Unregister(e.OldItems);
return;
case NotifyCollectionChangedAction.Add:
Register(e.NewItems);
return;
}
}
protected void Unregister(IList oldItems)
{
foreach (T item in oldItems)
{
item.PropertyChanged -= ItemPropertyChanged;
item.ElementCommitted -= ItemElementCommitted;
}
}
protected void Register(IList oldItems)
{
foreach (T item in oldItems)
{
item.PropertyChanged += ItemPropertyChanged;
item.ElementCommitted += ItemElementCommitted;
}
}
void ItemElementCommitted(object sender, BuryableBaseClass committedElement)
{
T element = committedElement as T;
if (committedElement.Deleted)
{
Console.WriteLine(String.Format("removing element of type: {0}", typeof(T)));
this.Remove(element);
}
}
void ItemPropertyChanged(object sender, PropertyChangedEventArgs args)
{
Console.WriteLine(String.Format("NotifyPropertyChangedPropertyChanged: {0}", args.PropertyName));
}
#region Implementation of ITransactionEnabled
public virtual List<Exception> TransactionExceptions
{
get
{
List<Exception> retVal = new List<Exception>();
foreach (ITransactionEnabled itm in this)
{
retVal.AddRange(itm.TransactionExceptions);
}
return retVal;
}
}
public virtual bool Save()
{
return !this.Any(a => !a.Save());
}
public virtual void Commit()
{
for (int i = this.Count - 1; i >= 0; i--)
{
this[i].Commit();
}
}
public virtual void Rollback()
{
for (int i = this.Count - 1; i >= 0; i--)
{
this[i].Rollback();
}
}
#endregion
}
这篇关于控制从ObservableCollection派生的类中元素的可访问性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!