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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1299920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:52:22  来源:igfitidea点击:

How to handle add to list event?

c#eventslistevent-handling

提问by Tomasz Smykowski

I have a list like this:

我有一个这样的清单:

List<Controls> list = new List<Controls>

How to handle adding new position to this list?

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

When I do:

当我做:

myObject.myList.Add(new Control());

I would like to do something like this in my object:

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

myList.AddingEvent += HandleAddingEvent

And then in my HandleAddingEventdelegate handling adding position to this list. How should I handle adding new position event? How can I make this event available?

然后在我的HandleAddingEvent委托处理中向此列表添加位置。我应该如何处理添加新位置事件?我怎样才能使这个活动可用?

采纳答案by Paolo Tedesco

You could inherit from List and add your own handler, something like

您可以从 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...");
        }
    }
}

Warning

警告

  1. Be aware that you have to re-implement all methods which add objects to your list. AddRange()will not fire this event, in this implementation.

  2. We did not overloadthe method. We hid the original one. If you Add()an object while this class is boxed in List<T>, the event will not be fired!

  1. 请注意,您必须重新实现所有将对象添加到列表中的方法。AddRange()在这个实现中不会触发这个事件。

  2. 我们没有重载该方法。我们把原来的藏了起来。如果你Add()是一个对象,而这个类被装箱List<T>则不会触发事件

MyList<int> l = new MyList<int>();
l.OnAdd += new EventHandler(l_OnAdd);
l.Add(1); // Will work

List<int> baseList = l;
baseList.Add(2); // Will NOT work!!!

回答by John Saunders

You can't do this with List<T>. However, you can do it with ObservableCollection<T>. See ObservableCollection<T>Class.

你不能用List<T>. 但是,您可以使用ObservableCollection<T>. 见ObservableCollection<T>

回答by JaredPar

What you need is a class that has events for any type of modification that occurs in the collection. The best class for this is BindingList<T>. It has events for every type of mutation which you can then use to modify your event list.

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

回答by Daniel Brückner

You cannot do this with standard collections out of the box - they just don't support change notifications. You could build your own class by inheriting or aggregating a existing collection type or you could use BindingList<T>that implements IBindingListand supports change notifications via the ListChangedevent.

您不能使用开箱即用的标准集合来做到这一点 - 它们只是不支持更改通知。您可以通过继承或聚合现有集合类型来构建您自己的类,或者您可以使用BindingList<T>IBindingList通过ListChanged事件实现和支持更改通知。

回答by MattH

I believe What you're looking for is already part of the API in the ObservableCollection(T)class. Example:

我相信你正在寻找的已经是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);

回答by Ahmad

One simple solution is to introduce an Add method for the list in your project and handle the event there. It doesn't answer the need for an event handler but can be useful for some small projects.

一个简单的解决方案是为项目中的列表引入一个 Add 方法并在那里处理事件。它不满足对事件处理程序的需求,但对一些小项目很有用。

AddToList(item) // or
AddTo(list,item)
////////////////////////

void AddTo(list,item)
{
    list.Add(item);
    // event handling
}

instead of

代替

list.Add(item);

回答by jayflo

To piggy-back off Ahmad's use of Extension Methods, you can create your own class where the list is private with a public getmethod and a public addmethod.

为了利用 Ahmad 对扩展方法的使用,您可以创建自己的类,其中列表是私有的,具有公共get方法和公共add方法。

public class MyList
{
    private List<SomeClass> PrivateSomeClassList;
    public List<SomeClass> SomeClassList
    {
        get
        {
            return PrivateSomeClassList;
        }
    }

    public void Add(SomeClass obj)
    {
        // do whatever you want
        PrivateSomeClassList.Add(obj);
    }
}

However, this class only provides access to List<>methods that you manually expose...hence may not be useful in cases where you need a lot of that functionality.

但是,此类仅提供对List<>您手动公开的方法的访问......因此在您需要大量该功能的情况下可能没有用。

回答by CRCarpenter

No need for adding an event just add the method.

无需添加事件,只需添加方法即可。

public class mylist:List<string>
{
  public void Add(string p)
  {
     // Do cool stuff here
     base.Add(p);
  }
}

回答by kara

To be clear: If you only need to observe the standard-functionalities you should use ObservableCollection(T)or other existing classes. Never rebuild something you already got.

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

..But.. If you need special events and have to go deeper, you should not derive from List! If you derive from List you can not overloead Add()in order to see every add.

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

Example:

例子:

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!
}

It's not allowed to override Add(), because you could mees up the functionalities of the base class (Liskov substitution principle).

不允许覆盖Add(),因为您可以找到基类的功能(Liskov 替换原则)。

But as always we need to make it work. But if you want to build your own list, you should to it by implementing the an interface: IList<T>.

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

Example which implements a before- and after-add event:

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

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
}

Now we've got all methods we want and didn't have to implement much. The main change in our code is, that our variables will be IList<T>instead of List<T>, ObservableCollection<T>or what ever.

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

And now the big wow: All of those implement IList<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>();

Which brings us to the next point: Use Interfaces instead of classes. Your code should never depend on implementation-details!

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