I have a custom INotifyCollectionChanged
class, which essentially just wraps around the standard ObservableCollection
. Whenever something is added/removed, the CollectionChanged
event is raised as expected. However, when I try to listen to this event using a WeakEventListener
, the listener never receives the event. Why is this happening and how do I fix this?
In below sample, I'd expect a NotImplementedException
to be thrown, but the test case succeeds (which clearly indicates that the event is truly raised). If you change the collection to be an ObservableCollection
instead of a Wrapper
, the exception does get thrown as expected.
public class Test : IWeakEventListener
{
private class Wrapper : INotifyCollectionChanged
{
private readonly ObservableCollection<string> _internal
= new ObservableCollection<string>();
public void Add(string s)
{
_internal.Add(s);
}
public event NotifyCollectionChangedEventHandler CollectionChanged
{
add { _internal.CollectionChanged += value; }
remove { _internal.CollectionChanged -= value; }
}
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
throw new NotImplementedException();
}
[Test]
public void CustomCollectionTest()
{
//change to new ObservableCollection<string>() and the exception gets thrown
var collection = new Wrapper();
var raised = false;
collection.CollectionChanged += (o, e) => raised = true;
CollectionChangedEventManager.AddListener(collection, this);
collection.Add("foobar");
Assert.True(raised);
}
}
Possibly related but still unanswered:
Why WeakEventManager does not fire an event when the sender is not the nominal?
As to why, the issue is the same as in this question. Essentially, the source registered with the event manager has to be the same as the sender of the event.
As a workaround for this limitation, I just have to make sure that the Wrapper
sends the event, rather than directly using the event on the wrapped collection.
private class Wrapper : INotifyCollectionChanged
{
private readonly ObservableCollection<string> _internal
= new ObservableCollection<string>();
public Wrapper()
{
_internal.CollectionChanged += OnInternalChanged;
}
public void Add(string s)
{
_internal.Add(s);
}
private void OnInternalChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var toRaise = CollectionChanged;
if (toRaise != null)
toRaise(this, e);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
}