Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<T> firing Event on Change

Tags:

c#

.net

I created a Class EventList inheriting List which fires an Event each time something is Added, Inserted or Removed:

public class EventList<T> : List<T>
{
    public event ListChangedEventDelegate ListChanged;
    public delegate void ListChangedEventDelegate();

    public new void Add(T item)
    {
        base.Add(item);
        if (ListChanged != null
            && ListChanged.GetInvocationList().Any())
        {
            ListChanged();
        }
    }
    ...
}

At the Moment I use it as a Property like this:

public EventList List
{
    get { return m_List; }
    set
    {
        m_List.ListChanged -= List_ListChanged;

        m_List = value;

        m_List.ListChanged += List_ListChanged;
        List_ListChanged();
    }
}

Now my Problem is, can I somehow handle if a new Object is referred to it or prevent that, so I do not have to do the event wiring stuff in the setter?

Of course, I can change the property to "private set" but I would like to be able to use the class as variable as well.

like image 348
Martin Avatar asked Oct 08 '12 15:10

Martin


Video Answer


1 Answers

You seldom create a new instance of a collection class in a class. Instantiate it once and clear it instead of creating a new list. (and use the ObservableCollection since it already has the INotifyCollectionChanged interface inherited)

private readonly ObservableCollection<T> list;
public ctor() {
    list = new ObservableCollection<T>();
    list.CollectionChanged += listChanged;
}

public ObservableCollection<T> List { get { return list; } }

public void Clear() { list.Clear(); }

private void listChanged(object sender, NotifyCollectionChangedEventArgs args) {
   // list changed
}

This way you only have to hook up events once, and can "reset it" by calling the clear method instead of checking for null or equality to the former list in the set accessor for the property.


With the changes in C#6 you can assign a get property from a constructor without the backing field (the backing field is implicit)

So the code above can be simplified to

public ctor() {
    List = new ObservableCollection<T>();
    List.CollectionChanged += OnListChanged;
}

public ObservableCollection<T> List { get; }

public void Clear()
{
    List.Clear();
}

private void OnListChanged(object sender, NotifyCollectionChangedEventArgs args)
{
   // react to list changed
}
like image 180
Patrick Avatar answered Sep 20 '22 15:09

Patrick