2009-11-04 15 views
5

Chciałbym wykonać pewne przetwarzanie przed dodaniem elementu do listy BindingList. Widzę, że istnieje zdarzenie ListChanged, ale jest ono uruchamiane po dodaniu elementu. Zdarzenie AddingNew jest uruchamiane tylko wtedy, gdy wywoływana jest metoda AddNew (nie jest to metoda Add). Czy ktoś wcześniej robił coś takiego?Jak mogę uruchomić zdarzenie przed dodaniem elementu do kolekcji w języku C#?

UPDATE:

Stworzyłem następujących klas i gdy metoda dodawania nazywa na IList, moja nowa metoda dodawania zostaje wyzwolony. Czy mam problem z castingiem, który czytałem w innych miejscach? Jeśli usunięto interfejs ISpecialCollection z kolekcji, moja metoda Add nie zostanie wywołana. Czy ktoś może wyjaśnić, dlaczego działa inaczej? Czy mam problem z przesyłaniem, jeśli korzystam z interfejsu ISpecialCollection <?

public interface ISpecialCollection<T> : IList<T> 
{ 
} 

public class SpecialCollection<T> : BindingList<T>, ISpecialCollection<T> 
{ 
    public new void Add (T item) 
    { 
    base.Add(item);  
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
    IList<ItemType> list = new SpecialCollection<ItemType>(); 
    list.Add(new ItemType()); 
    } 
} 
+0

Jeff A.mówi gdzieś, że wartość jest mocno buforowana i że aktualizacja może potrwać kilka godzin. –

Odpowiedz

3

Należy zastąpić chronioną metodę BindingList.InsertItem (MSDN). Add, Insert i tacy wszyscy nazywają to, aby faktycznie dodawać i podnosić odpowiednie zdarzenia. Podnieś swoje wydarzenie, a następnie zadzwoń pod numer base.InsertItem, aby zrobić resztę.

1

Coś jak:

public class PreProcessBindingList<T> : Collection<T> 
    { 
     public AddingNewEventHandler AddingNew; 

     public override void Add(T item) 
     { 
      PreProcess(item); 
      base.Add(item); 

      AddingNewEventHandler addingNew = this.AddingNew; 
      if (addingNew != null) 
      { 
       addingNew(this, new AddingNewEventArgs(item)); 
      } 
     } 
    } 
+0

Wiem, ale słyszałem, że może to powodować problemy, jeśli ktoś rzuci to jako listę i wywoła Add. W takim przypadku nowa metoda Add nie zostanie wywołana. – bsh152s

+0

Tak, chcesz go przesłonić, a nie ukryć. –

+0

Nie można zastąpić metody BindingList.Add. Najlepsze, co możesz zrobić, to ukryć. – Ian

2

Zrobiłem coś podobnego jak ja potrzebowałem uchwycić zdarzenia ItemAdding i ItemAdded

Magia bit jest nowe słowo kluczowe, które zastąpi odziedziczone klasy metoda

// class that inherits generic List and hides the add item 
public class ListWithEvents<T> : List<T> 
    { 
     public event EventHandler ItemAdding; 
     public event EventHandler ItemAdded; 

     public new void Add(T item) 
     { 
      if (ItemAdding != null) 
       ItemAdding(item, EventArgs.Empty); 

      base.Add(item); 

      if (ItemAdded != null) 
       ItemAdded(item, EventArgs.Empty); 

     } 
    } 

// Using the class 
protected override void OnLoad(EventArgs e) 
    { 

     ListWithEvents<int> lstI = new ListWithEvents<int>(); 
     lstI.ItemAdded += new EventHandler(lstI_ItemAdded); 
     lstI.ItemAdding += new EventHandler(lstI_ItemAdding); 
    } 

    void lstI_ItemAdding(object sender, EventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    void lstI_ItemAdded(object sender, EventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 
3

Najprostszą drogą jest podklasa Collection<T> klasa. Jest to klasa kolekcji w BCL, która ma być podklasowana i ma swoje zachowanie nadpisane. Podklasy innych typów, takich jak BindingList<T> lub List<T> po prostu powodują ból.

Po podklasie Collection<T> można nadpisać Dodaj i utworzyć własne wydarzenie do odsłuchania.

0

Właściwym sposobem na to jest rozszerzenie Collection<T> i zastąpienie metody InsertItem. Możesz podnieść swoje wydarzenie tam przed wywołaniem base.InsertItem.

0

Użyj biblioteki kolekcji C5. Kolekcje C5 są już skonfigurowane, aby móc wywoływać zdarzenia związane z kilkoma operacjami, w tym usuwanie kolekcji, dodawanie elementów, usuwanie elementów, wstawianie elementów i ogólne zmiany kolekcji.

Jak dobrze, zbiory biblioteczne C5 wdrożenia System.Collection.GenericICollection i IList interfejsy w stosownych przypadkach, a więc mogą być usuwane jako realizację nawet jeśli biblioteka jest oczekując tylko, na przykład SCG.ICollection.

EDYCJA: Zapomniałem podać część Twoich wymagań; wiele z tych zdarzeń, o których wspomniałem powyżej, jest zdarzeniami podlegającymi anulowaniu i są uruchamiane, zanim akcja wpłynie na kolekcję bazową, umożliwiając wprowadzanie zmian lub odrzucanie dodatków, usunięć itp.

-1

Użyj ObservableCollection. Ma zdarzenia monitorujące, kiedy kolekcja się zmienia. Uważam, że jest on używany przede wszystkim do WPF, ale użyłem go również w projektach ASP.NET.

+1

... ObservableCollection (Of T) ... w przestrzeni nazw System.Collections.ObjectModel w pliku WindowsBase.dll. – crazytmack

+0

ObservableCollection zawiera tylko zdarzenia pocztowe, ale pytanie dotyczy pre zdarzeń. Będziesz musiał dziedziczyć po ObservableCollection i przesłonić członków, aby uzyskać pożądane zachowanie. –

Powiązane problemy