首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >发生变化的List<T>触发事件

发生变化的List<T>触发事件
EN

Stack Overflow用户
提问于 2012-10-08 15:43:17
回答 5查看 54.6K关注 0票数 16

我创建了一个类EventList继承List,它在每次添加、插入或删除某些内容时触发一个事件:

代码语言:javascript
复制
public class EventList<T> : List<T>
{
    public event ListChangedEventDelegate ListChanged;
    public delegate void ListChangedEventDelegate();

    public new void Add(T item)
    {
        base.Add(item);
        if (ListChanged != null
            && ListChanged.GetInvocationList().Any())
        {
            ListChanged();
        }
    }
    ...
}

现在我把它用作这样的财产:

代码语言:javascript
复制
public EventList List
{
    get { return m_List; }
    set
    {
        m_List.ListChanged -= List_ListChanged;

        m_List = value;

        m_List.ListChanged += List_ListChanged;
        List_ListChanged();
    }
}

现在我的问题是,如果一个新的对象被引用或阻止它,我能以某种方式处理它吗?所以我不需要在setter中做事件连接?

当然,我可以将属性更改为“私有集”,但我也希望能够将类作为变量使用。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-10-08 15:56:53

您很少在类中创建集合类的新实例。实例化它一次并清除它,而不是创建一个新列表。(并使用ObservableCollection,因为它已经继承了INotifyCollectionChanged接口)

代码语言:javascript
复制
private readonly ObservableCollection<T> list;
public ctor() {
    list = new ObservableCollection<T>();
    list.CollectionChanged += listChanged;
}

public ObservableCollection<T> List { get { return list; } }

public void Clear() { list.Clear(); }

private void listChanged(object sender, NotifyCollectionChangedEventArgs args) {
   // list changed
}

通过这种方式,您只需要连接事件一次,并且可以通过调用clear方法来“重置”事件,而不是检查属性的set访问器中的前一个列表是否为null或相等。

使用C#6中的更改,您可以从构造函数中分配一个get属性,而不需要支持字段(支持字段是隐式的)

因此,上面的代码可以简化为

代码语言:javascript
复制
public ctor() {
    List = new ObservableCollection<T>();
    List.CollectionChanged += OnListChanged;
}

public ObservableCollection<T> List { get; }

public void Clear()
{
    List.Clear();
}

private void OnListChanged(object sender, NotifyCollectionChangedEventArgs args)
{
   // react to list changed
}
票数 26
EN

Stack Overflow用户

发布于 2012-10-08 15:48:24

ObservableCollection是一个带有CollectionChanged事件的列表

ObservableCollection.CollectionChanged事件

有关如何连接事件处理程序,请参见Patrick的答复。+1

不确定您在寻找什么,但我将其用于一个集合,其中一个事件触发添加、删除和更改。

代码语言:javascript
复制
public class ObservableCollection<T>: INotifyPropertyChanged
{
    private BindingList<T> ts = new BindingList<T>();

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property. 
    // The CallerMemberName attribute that is applied to the optional propertyName 
    // parameter causes the property name of the caller to be substituted as an argument. 
    private void NotifyPropertyChanged( String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public BindingList<T> Ts
    {
        get { return ts; }
        set
        {
            if (value != ts)
            {
                Ts = value;
                if (Ts != null)
                {
                    ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
                    {
                        OnListChanged(this);
                    };
                }
                NotifyPropertyChanged("Ts");
            }
        }
    }

    private static void OnListChanged(ObservableCollection<T> vm)
    {
        // this will fire on add, remove, and change
        // if want to prevent an insert this in not the right spot for that 
        // the OPs use of word prevent is not clear 
        // -1 don't be a hater
        vm.NotifyPropertyChanged("Ts");
    }

    public ObservableCollection()
    {
        ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
        {
            OnListChanged(this);
        };
    }
}
票数 12
EN

Stack Overflow用户

发布于 2012-10-08 16:01:46

如果不希望或不能转换为可观察的集合,请尝试如下:

代码语言:javascript
复制
public class EventList<T> : IList<T> /* NOTE: Changed your List<T> to IList<T> */
{
  private List<T> list; // initialize this in your constructor.
  public event ListChangedEventDelegate ListChanged;
  public delegate void ListChangedEventDelegate();

  private void notify()
  {
      if (ListChanged != null
          && ListChanged.GetInvocationList().Any())
      {
        ListChanged();
      }
  }

  public new void Add(T item)
  {
      list.Add(item);
      notify();
  }

  public List<T> Items {
    get { return list; } 
    set {
      list = value; 
      notify();
    }
  }
  ...
}

现在,对于您的属性,您应该能够将代码简化为:

代码语言:javascript
复制
public EventList List
{
  get { return m_List.Items; }
  set
  {
      //m_List.ListChanged -= List_ListChanged;

      m_List.Items = value;

      //m_List.ListChanged += List_ListChanged;
      //List_ListChanged();
  }
}

为什么?在EventList.Items中设置任何东西都会调用您的私有notify()例程。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12785019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档