我创建了一个继承List的Class EventList,每次添加,插入或删除时都触发一个Event:
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();
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
在片刻我将它用作这样的属性:
public EventList List
{
get { return m_List; }
set
{
m_List.ListChanged -= List_ListChanged;
m_List = value;
m_List.ListChanged += List_ListChanged;
List_ListChanged();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,我可以以某种方式处理一个新的对象是否被引用或阻止它,所以我不必在setter中做事件接线?
当然,我可以将属性更改为"私有集",但我希望能够将该类用作变量.
Pat*_*ick 16
您很少在类中创建集合类的新实例.实例化一次并清除它而不是创建新列表.(并使用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
}
Run Code Online (Sandbox Code Playgroud)
这样,您只需连接事件一次,并且可以通过调用clear方法"重置它",而不是检查null或与属性的set访问器中的前一个列表相等.
通过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
}
Run Code Online (Sandbox Code Playgroud)
pap*_*zzo 11
ObservableCollection是一个带有CollectionChanged事件的List
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);
};
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不想或不能转换为Observable Collection,请尝试以下方法:
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();
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
现在,对于您的属性,您应该能够将代码减少到:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么?在EventList.Items中设置任何内容都将调用您的私有notify()
例程.
归档时间: |
|
查看次数: |
37099 次 |
最近记录: |