首页 > 解决方案 > 当`List中`T`的属性发生变化时如何实现和触发事件` 在所属类中

问题描述

当所属类T中的属性发生更改时如何实现和触发事件List<T>

我的意思是,不是在集合本身上,而是在T.

有什么模式怎么做吗?

我当前的代码

public class Section
{
    public string Title { get; set; }
    public List<Question> Questions { get; set; } = new List<Question>();

    public int AnsweredQuestion
    {
        get
        {
            return Questions.Count(x => x.State != DeviceNodeTechStateEnum.Undefined);
        }
    }

    public int NonAnsweredQuestion
    {
        get
        {

            return Questions.Count(x => x.State == DeviceNodeTechStateEnum.Undefined);
        }
    }

    public string QuestionStats
    {
        get
        {
            return string.Format("{0}/{1}", AnsweredQuestion, Questions.Count);
        }
    }
}

public class Question : INotifyPropertyChanged
{
    public Guid ID { get; set; }

    public string _note { get; set; }
    public string Note
    {
        get
        {
            return this._note;
        }

        set
        {
            if (value != this._note)
            {
                this._note = value;
                NotifyPropertyChanged();
            }
        }
    }

    private DeviceNodeTechStateEnum _state { get; set; }
    public DeviceNodeTechStateEnum State
    {
        get
        {
            return this._state;
        }

        set
        {
            if (value != this._state)
            {
                this._state = value;
                NotifyPropertyChanged();
            }
        }
    } 

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

基本上我需要知道班级是否public DeviceNodeTechStateEnum State有变化Section

标签: c#eventscollections

解决方案


我以前使用过这种模式,您基本上包装一个列表,扩展它以实现 INotifyPropertyChanged,并挂钩到任何从列表中添加、插入或删除项目的方法,以便您可以连接/取消连接项目 PropertyChanged 事件。

public class ItemPropertyChangedNotifyingList<T> : IList<T>, INotifyPropertyChanged where T : INotifyPropertyChanged
{
    private List<T> _listImplementation = new List<T>();

    public void Add(T item)
    {
        item.PropertyChanged += ItemOnPropertyChanged;
        _listImplementation.Add(item);
    }

    private void ItemOnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(sender, e);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _listImplementation.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable) _listImplementation).GetEnumerator();
    }

    public void Clear()
    {
        _listImplementation.ForEach(x => x.PropertyChanged -= ItemOnPropertyChanged);
        _listImplementation.Clear();
    }

    public bool Contains(T item)
    {
        return _listImplementation.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        _listImplementation.CopyTo(array, arrayIndex);
    }

    public bool Remove(T item)
    {
        item.PropertyChanged -= ItemOnPropertyChanged;
        return _listImplementation.Remove(item);
    }

    public int Count => _listImplementation.Count;

    public bool IsReadOnly => false;

    public int IndexOf(T item)
    {
        return _listImplementation.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        item.PropertyChanged += ItemOnPropertyChanged;
        _listImplementation.Insert(index, item);
    }

   public void RemoveAt(int index)
    {
        if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index));
        _listImplementation[index].PropertyChanged -= ItemOnPropertyChanged;
        _listImplementation.RemoveAt(index);
    }

    public T this[int index]
    {
        get => _listImplementation[index];
        set => _listImplementation[index] = value;
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

在处理此包装列表的 PropertyChanged 事件时,sender参数将是引发事件的项目的实例。


推荐阅读