我创建了一个类EventList继承List,它在每次添加、插入或删除某些内容时触发一个事件:
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();
}
}
...
}现在我把它用作这样的财产:
public EventList List
{
get { return m_List; }
set
{
m_List.ListChanged -= List_ListChanged;
m_List = value;
m_List.ListChanged += List_ListChanged;
List_ListChanged();
}
}现在我的问题是,如果一个新的对象被引用或阻止它,我能以某种方式处理它吗?所以我不需要在setter中做事件连接?
当然,我可以将属性更改为“私有集”,但我也希望能够将类作为变量使用。
发布于 2012-10-08 15:56:53
您很少在类中创建集合类的新实例。实例化它一次并清除它,而不是创建一个新列表。(并使用ObservableCollection,因为它已经继承了INotifyCollectionChanged接口)
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属性,而不需要支持字段(支持字段是隐式的)
因此,上面的代码可以简化为
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
}发布于 2012-10-08 15:48:24
ObservableCollection是一个带有CollectionChanged事件的列表
ObservableCollection.CollectionChanged事件
有关如何连接事件处理程序,请参见Patrick的答复。+1
不确定您在寻找什么,但我将其用于一个集合,其中一个事件触发添加、删除和更改。
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);
};
}
}发布于 2012-10-08 16:01:46
如果不希望或不能转换为可观察的集合,请尝试如下:
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();
}
}
...
}现在,对于您的属性,您应该能够将代码简化为:
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()例程。
https://stackoverflow.com/questions/12785019
复制相似问题