如何处理添加到列表事件?

Tom*_*ski 40 c# events list event-handling

我有一个这样的列表:

List<Controls> list = new List<Controls>
Run Code Online (Sandbox Code Playgroud)

如何处理在此列表中添加新位置?

当我做:

myObject.myList.Add(new Control());
Run Code Online (Sandbox Code Playgroud)

我想在我的对象中做这样的事情:

myList.AddingEvent += HandleAddingEvent
Run Code Online (Sandbox Code Playgroud)

然后在我的HandleAddingEvent委托处理中添加位置到此列表.我该如何处理添加新的位置事件?我怎样才能举办这个活动?

Mat*_*ttH 66

我相信您正在寻找的内容已经是ObservableCollection(T)类中API的一部分.例:

ObservableCollection<int> myList = new ObservableCollection<int>();

myList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
    delegate(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)                    
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            MessageBox.Show("Added value");
        }
    }
);

myList.Add(1);
Run Code Online (Sandbox Code Playgroud)

  • ObservableCollection <T>看起来是完成此任务的正确方法. (2认同)

Pao*_*sco 40

您可以从List继承并添加自己的处理程序,例如

using System;
using System.Collections.Generic;

namespace test
{
    class Program
    {

        class MyList<T> : List<T>
        {

            public event EventHandler OnAdd;

            public new void Add(T item) // "new" to avoid compiler-warnings, because we're hiding a method from base-class
            {
                if (null != OnAdd)
                {
                    OnAdd(this, null);
                }
                base.Add(item);
            }
        }

        static void Main(string[] args)
        {
            MyList<int> l = new MyList<int>();
            l.OnAdd += new EventHandler(l_OnAdd);
            l.Add(1);
        }

        static void l_OnAdd(object sender, EventArgs e)
        {
            Console.WriteLine("Element added...");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,AddRange()如果您想知道添加的内容等,还应该重新实现,声明自己的事件类型,这只是一个基本想法......

  • ObservableCollection <T>不会提供这个吗? (38认同)
  • MattH是正确的,这是更好的解决方案.BindingList <T>也是一个解决方案.http://msdn.microsoft.com/en-us/library/ms132742.aspx (4认同)
  • `ObservableCollection <T>`引发事件_after_动作,而不是之前.但是`BindingList <T>`有`AddingNew`事件 (4认同)

Jar*_*Par 26

您需要的是一个类,它包含集合中发生的任何类型修改的事件.对此最好的类是BindingList<T>.它具有针对每种类型的突变的事件,您可以使用它们来修改事件列表.

  • 根据我的经验,`AddingNew` 事件并不总是被触发。带有 `e.ListChangedType == ListChangedType.ItemAdded` 的 `ListChanged` 事件更加健壮 (2认同)

Joh*_*ers 16

你不能这样做List<T>.但是,你可以这样做ObservableCollection<T>.见ObservableCollection<T>.


kar*_*ara 7

需要明确的是:如果您只需要观察标准功能,您应该使用ObservableCollection(T)或其他现有类。永远不要重建你已经拥有的东西。

..但是.. 如果您需要特殊事件并且必须更深入,那么您不应该从 List 派生!如果您从 List 派生,则无法超载Add()以查看每个添加。

例子:

public class MyList<T> : List<T>
{
    public void Add(T item) // Will show us compiler-warning, because we hide the base-mothod which still is accessible!
    {
        throw new Exception();
    }
}

public static void Main(string[] args)
{
    MyList<int> myList = new MyList<int>(); // Create a List which throws exception when calling "Add()"
    List<int> list = myList; // implicit Cast to Base-class, but still the same object

    list.Add(1);              // Will NOT throw the Exception!
    myList.Add(1);            // Will throw the Exception!
}
Run Code Online (Sandbox Code Playgroud)

不允许重写Add(),因为你可能会满足基类的功能(里氏替换原则)。

但一如既往,我们需要让它发挥作用。但如果你想构建自己的列表,你应该通过实现接口来实现IList<T>

实现添加前和添加后事件的示例:

public class MyList<T> : IList<T>
{
    private List<T> _list = new List<T>();

    public event EventHandler BeforeAdd;
    public event EventHandler AfterAdd;

    public void Add(T item)
    {
        // Here we can do what ever we want, buffering multiple events etc..
        BeforeAdd?.Invoke(this, null);
        _list.Add(item);
        AfterAdd?.Invoke(this, null);
    }

    #region Forwarding to List<T>
    public T this[int index] { get => _list[index]; set => _list[index] = value; }
    public int Count => _list.Count;
    public bool IsReadOnly => false;
    public void Clear() => _list.Clear();
    public bool Contains(T item) => _list.Contains(item);
    public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);
    public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
    public int IndexOf(T item) => _list.IndexOf(item);
    public void Insert(int index, T item) => _list.Insert(index, item);
    public bool Remove(T item) => _list.Remove(item);
    public void RemoveAt(int index) => _list.RemoveAt(index);
    IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

现在我们已经有了我们想要的所有方法,并且不需要实现太多。我们代码中的主要变化是,我们的变量将IList<T>代替List<T>,ObservableCollection<T>或其他什么。

现在最令人惊叹的是:所有这些都实现了IList<T>

IList<int> list1 = new ObservableCollection<int>();
IList<int> list2 = new List<int>();
IList<int> list3 = new int[10];
IList<int> list4 = new MyList<int>();
Run Code Online (Sandbox Code Playgroud)

这给我们带来了下一点:使用接口而不是类。您的代码永远不应该依赖于实现细节!