How can I fire event before item is added to collection in C#?
Asked Answered
I

7

5

I would like to do some processing before an item is added to a BindingList. I see there is an ListChanged event but this is fired after the item is added. The AddingNew event is only fired when the AddNew method (not the Add method) is called. Has anyone done something like this before?

UPDATE:

I have created the following classes and when the Add method is called on the IList, my new Add method gets triggered. So, do I have the casting problem that I've read in other places? If I removed the ISpecialCollection interface from the collection, my Add method doesn't get called. Can someone explain why it's acting differently? Do I have the casting problem if I use the ISpecialCollection< interface?

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());
  }
}
Ina answered 4/11, 2009 at 14:49 Comment(1)
Jeff A. says somewhere that the value is heavily cached, and that it can take a couple of hours to be updated.Lorsung
M
3

You should override the protected BindingList.InsertItem method (MSDN). Add, Insert and such all call this to do the actual adding adding and raise appropriate events. Raise your event, and then call base.InsertItem to do the rest.

Majordomo answered 4/11, 2009 at 16:2 Comment(0)
P
3

The most straightforward route is to subclass the Collection<T> class. This is the collection class in the BCL which is designed to be subclassed and have it's behavior overriden. Subclassing other types like BindingList<T> or List<T> will just cause you pain.

Once you subclass Collection<T>, you can override Add and create your own event to listen to.

Powerhouse answered 4/11, 2009 at 15:53 Comment(0)
M
3

You should override the protected BindingList.InsertItem method (MSDN). Add, Insert and such all call this to do the actual adding adding and raise appropriate events. Raise your event, and then call base.InsertItem to do the rest.

Majordomo answered 4/11, 2009 at 16:2 Comment(0)
R
2

I have done something similar as I needed to capture the ItemAdding and ItemAdded event

The magic bit is the new keyword that will override the inherited class' method

// 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();
    }
Reword answered 4/11, 2009 at 15:52 Comment(0)
I
1

Something like:

  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));
            }
        }
    }
Indistinguishable answered 4/11, 2009 at 14:53 Comment(3)
I know but I've heard this could cause problems if someone casts it as an List and calls Add. In that case, the new Add method would not be called.Ina
Yeah, you'd want to override it, not hide it.Priorate
You can't override the BindingList.Add method. The best you can do is hide it.Indistinguishable
S
0

The right way to do this is to extend Collection<T> and override the InsertItem method. You can raise your event there before calling base.InsertItem.

Sites answered 4/11, 2009 at 16:13 Comment(0)
D
0

Use the C5 collections library. C5's collections are already set up to be able to fire events on several operations, including clearing the collection, adding items, removing items, inserting items, and general collection changes.

As well, the C5 library collections implement the System.Collection.Generic ICollection and IList interfaces where appropriate, and so can be dropped in as the implementation even if a library is only expecting, e.g. an SCG.ICollection.

EDIT: I forgot to mention a portion of your requirements; many of those events I mentioned above are cancelable events, and are fired before the action has affected the underlying collection, allowing you to make changes or reject additions, removals, etc.

Doable answered 5/11, 2009 at 17:33 Comment(0)
R
-1

Use ObservableCollection. It has events that monitor when the collection is changing. I believe that it is primarily used for WPF, but I have used it with ASP.NET projects also.

Reverential answered 17/1, 2010 at 4:17 Comment(2)
...ObservableCollection(Of T)...in the System.Collections.ObjectModel namespace in the WindowsBase.dll.Reverential
ObservableCollection only has post events, but the question asks about pre events. You would have to inherit from ObservableCollection and override members to get the desired behavior.Offside

© 2022 - 2024 — McMap. All rights reserved.