列出在更改时触发事件

我创建了一个inheritanceList的Class EventList ,每当添加,插入或删除某些内容时触发一个Event:

public class EventList : List { public event ListChangedEventDelegate ListChanged; public delegate void ListChangedEventDelegate(); public new void Add(T item) { base.Add(item); if (ListChanged != null && ListChanged.GetInvocationList().Any()) { ListChanged(); } } ... } 

在片刻,我使用它像这样的属性:

 public EventList List { get { return m_List; } set { m_List.ListChanged -= List_ListChanged; m_List = value; m_List.ListChanged += List_ListChanged; List_ListChanged(); } } 

现在我的问题是,我可以以某种方式处理新的对象是否被引用或阻止它,所以我不必在setter中做事件接线?

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

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

 private readonly ObservableCollection list; public ctor() { list = new ObservableCollection(); list.CollectionChanged += listChanged; } public ObservableCollection List { get { return list; } } public void Clear() { list.Clear(); } private void listChanged(object sender, NotifyCollectionChangedEventArgs args) { // list changed } 

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


通过C#6中的更改,您可以在没有支持字段的情况下从构造函数分配get属性(支持字段是隐式的)

所以上面的代码可以简化为

 public ctor() { List = new ObservableCollection(); List.CollectionChanged += OnListChanged; } public ObservableCollection List { get; } public void Clear() { List.Clear(); } private void OnListChanged(object sender, NotifyCollectionChangedEventArgs args) { // react to list changed } 

ObservableCollection是一个带有CollectionChanged事件的List

ObservableCollection.CollectionChanged事件

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

不知道你在寻找什么,但是我将它用于一个集合,其中包含一个在添加,删除和更改时触发的事件。

 public class ObservableCollection: INotifyPropertyChanged { private BindingList ts = new BindingList(); 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 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 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); }; } } 

如果您不想或不能转换为Observable Collection,请尝试以下方法:

 public class EventList : IList /* NOTE: Changed your List to IList */ { private List 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 Items { get { return list; } set { list = value; notify(); } } ... } 

现在,对于您的属性,您应该能够将代码减少到:

 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()例程。

如果ObservableCollection不是您的解决方案,您可以尝试:

A)实现一个自定义EventArgs,它将在触发事件时包含新的Count属性。

 public class ChangeListCountEventArgs : EventArgs { public int NewCount { get; set; } public ChangeListCountEventArgs(int newCount) { NewCount = newCount; } } 

B)实现从Listinheritance的自定义List,并根据您的需要重新定义Count属性和构造函数:

 public class CustomList : List { public event EventHandler ListCountChanged; public new int Count { get { ListCountChanged?.Invoke(this, new ChangeListCountEventArgs(base.Count)); return base.Count; } } public CustomList() { } public CustomList(List list) : base(list) { } public CustomList(CustomList list) : base(list) { } } 

C)最后订阅你的活动:

 var myList = new CustomList(); myList.ListCountChanged += (obj, e) => { // get the count thanks to e.NewCount }; 

当有人从IList.add(对象)调用Generic方法时,我有一个解决方案。 这样你也会得到通知。

 using System; using System.Collections; using System.Collections.Generic; namespace YourNamespace { public class ObjectDoesNotMatchTargetBaseTypeException : Exception { public ObjectDoesNotMatchTargetBaseTypeException(Type targetType, object actualObject) : base(string.Format("Expected base type ({0}) does not match actual objects type ({1}).", targetType, actualObject.GetType())) { } } ///  /// Allows you to react, when items were added or removed to a generic List. ///  public abstract class NoisyList : List, IList { #region Public Methods /******************************************/ int IList.Add(object item) { CheckTargetType(item); Add((TItemType)item); return Count - 1; } void IList.Remove(object item) { CheckTargetType(item); Remove((TItemType)item); } public new void Add(TItemType item) { base.Add(item); OnItemAdded(item); } public new bool Remove(TItemType item) { var result = base.Remove(item); OnItemRemoved(item); return result; } #endregion # region Private Methods /******************************************/ private static void CheckTargetType(object item) { var targetType = typeof(TItemType); if (item.GetType().IsSubclassOf(targetType)) throw new ObjectDoesNotMatchTargetBaseTypeException(targetType, item); } #endregion #region Abstract Methods /******************************************/ protected abstract void OnItemAdded(TItemType addedItem); protected abstract void OnItemRemoved(TItemType removedItem); #endregion } }