Come gestire aggiungere alla lista di eventi?

Ho una lista come questa:

List<Controls> list = new List<Controls>

Come gestire l’aggiunta nuova posizione di questo elenco?

Quando faccio:

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

Vorrei fare qualcosa di simile a questo nel mio oggetto:

myList.AddingEvent += HandleAddingEvent

E poi nel mio HandleAddingEvent delegato di movimentazione aggiunta di posizione di questo elenco. Come devo gestire l’aggiunta nuova posizione di evento? Come posso rendere questo evento disponibile?

  • Non utilizzare blockquote. Selezionare il testo e premere ctrl-K.

 

9 Replies
  1. 40

    Si potrebbe ereditare dalla Lista e aggiungere il proprio gestore, qualcosa di simile a

    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...");
            }
        }
    }

    Avvertenza

    1. Essere consapevoli che è necessario re-implementare tutti i metodi che aggiungere oggetti alla lista. AddRange() non verrà generato questo evento, in questa implementazione.

    2. Abbiamo non sovraccarico il metodo. Abbiamo nascosto di quella originale. Se si Add() un oggetto di questa classe è boxed in List<T>, il evento non sarà licenziato!

    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!!!
    • Non ObservableCollection<T> fornire già?
    • Mt è corretto, che sarebbe la soluzione migliore. BindingList<T> sarebbe anche una soluzione. msdn.microsoft.com/en-us/library/ms132742.aspx
    • ObservableCollection<T> solleva i suoi eventi dopo l’azione, non prima. Ma il BindingList<T> ha AddingNew evento
    • Né ObservableCollection o BindingList estendere Elenco. Si perde la funzionalità se li si usa.
    • ObservableCollection anche essere usato sul thread UI se contiene UI. stackoverflow.com/a/2092036/623561
  2. 65

    Credo che Quello che stai cercando è già parte di API nella ObservableCollection(T) classe. Esempio:

    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);
    • ObservableCollection<T> sembra il modo corretto per eseguire questa operazione.
    • ObservableCollection deve essere utilizzato sul thread UI se contiene UI. stackoverflow.com/a/2092036/623561
  3. 26

    Che cosa avete bisogno è di una classe di eventi per ogni tipo di modifica che si verifica nella collezione. La classe migliore per questo è BindingList<T>. Dispone di eventi per ogni tipo di mutazione che è possibile utilizzare per modificare la tua lista di eventi.

    • Nella mia esperienza AddingNew evento non è sempre stato licenziato. ListChanged evento con e.ListChangedType == ListChangedType.ItemAdded era più robusto
  4. 16

    Non si può fare questo con List<T>. Tuttavia, si può fare con ObservableCollection<T>. Vedere ObservableCollection<T> Classe.

    • Qual è la differenza con l’Elenco o una Raccolta, se hai ancora bisogno di calcolarlo? Non c’è alcuna eventi che si solleva quando la raccolta.
    • Buona pesca. Non so cosa stavo pensando. È ObservableCollection<T> che ha il eventi.
    • che è di destra 🙂 abbiamo avuto a punto qualcosa. ObservableCollection<T> e BindingList<T> sono in .Net 4.0; quindi, se avete bisogno di questa specialità .Net 3.5 o prima si doveva derivare Elenco o Raccolta e aggiungere eventi personalizzati.
    • Che non è corretto, ObservableCollection è in .NET 3.0 e 3.5. Spazio Dei Nomi: System.Collezioni.ObjectModel Montaggio: WindowsBase (in WindowsBase.dll)
  5. 2

    Una soluzione semplice è quella di introdurre un metodo Add per la lista nel vostro progetto e gestire l’evento. Non rispondere all’esigenza di un gestore di eventi, ma può essere utile per alcuni piccoli progetti.

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

    invece di

    list.Add(item);
  6. 2

    Per essere chiari: Se avete solo bisogno di osservare gli standard di funzionalità, si dovrebbe utilizzare ObservableCollection(T) o di altre classi esistenti. Mai ricostruire qualcosa che hai già ottenuto.

    ..Ma.. Se avete bisogno di eventi speciali e di andare più in profondità, si non dovrebbe derivare dalla Lista! Se si deriva dall’Elenco è possibile non overloead Add() per vedere ogni aggiungi.

    Esempio:

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

    Non è autorizzato a ignorare Add(), perché si potrebbe mees la funzionalità di base di classe (Liskov principio di sostituzione).

    Ma come sempre abbiamo bisogno per farlo funzionare. Ma se si desidera costruire la vostra lista, si dovrebbe implementando l’interfaccia: IList<T>.

    Esempio che implementa un prima e un dopo, aggiungi evento:

    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
    }

    Ora abbiamo tutti i metodi vogliamo e non ha bisogno di implementare molto. Il principale cambiamento nel nostro codice, che il nostro variabili saranno IList<T> invece di List<T>, ObservableCollection<T> o che cosa mai.

    E ora il grande wow: Tutti coloro implementare 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>();

    Che ci porta al punto successivo: Utilizzare le Interfacce invece di classi. Il codice dovrebbe mai fare affidamento su di attuazione-dettagli!

  7. 1

    Non si può fare questo con standard collezioni out of the box – solo che non supportano le notifiche di modifica. Si potrebbe costruire la propria classe che eredita o l’aggregazione di un insieme esistente di tipo o si potrebbe utilizzare BindingList<T> che implementa IBindingList e supporta le notifiche di modifica tramite il ListChanged evento.

    • Che c’è di sbagliato, come le altre risposte dire, ObservableCollection può fare.
  8. 1

    Di piggy-back off di Ahmad uso di Metodi di Estensione, è possibile creare la propria classe, dove la lista è privato pubblico get metodo e un pubblico add metodo.

    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);
        }
    }

    Questa classe, tuttavia, fornisce solo l’accesso a List<> metodi manualmente esporre…pertanto non può essere utile nei casi in cui avete bisogno di un sacco di funzionalità che.

  9. 0

    Senza bisogno di aggiunta di un evento semplicemente aggiungere il metodo.

    public class mylist:List<string>
    {
      public void Add(string p)
      {
         //Do cool stuff here
         base.Add(p);
      }
    }
    • (nuovo MyList() aus Elenco<string>).Add() non chiamare il tuo metodo! Non ignorare è solo nascondere il metodo di base.

Lascia un commento