控制从ObservableCollection派生的类中元素的可访问性 [英] Control accessability of elements in a class derived from ObservableCollection

查看:146
本文介绍了控制从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆