Weak INotifyPropertyChanged and INotifyCollectionChanged Listeners

August 14, 2009

Following on from my woes about ObservableCollection<T>, and my annoyance at having to maintain a parallel collection to ensure all INotifyPropertyChanged and INotifyCollectionChanged subscriptions are removed, I decided to look down the avenue of Weak event subscriptions.  To that end I can up with the classes WeakPropertyChangedListner and WeakCollectionChangedListener.  The code for these is as follows:

 

    public class WeakPropertyChangedListener
    {
        #region Private Fields
        private INotifyPropertyChanged _source;
        private WeakReference _listener;
        #endregion

        #region Ctor
        public WeakPropertyChangedListener(INotifyPropertyChanged source, PropertyChangedEventHandler listener)
        {
            this._source = source;
            this._source.PropertyChanged += this.OnPropertyChanged;
            this._listener = new WeakReference(listener);
        }
        #endregion

        #region Public Methods
        public static WeakPropertyChangedListener Create(INotifyPropertyChanged source, PropertyChangedEventHandler listener)
        {
            return new WeakPropertyChangedListener(source, listener);
        }

        public void Disconnect()
        {
            if (_source != null)
            {
                _source.PropertyChanged -= this.OnPropertyChanged;
                _source = null;
                _listener = null;
            }
        }
        #endregion

        #region Private Methods
        private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (_listener != null)
            {
                var handler = _listener.Target as PropertyChangedEventHandler;
                if (handler != null)
                {
                    handler(sender, e);
                }
                else
                {
                    this.Disconnect();
                }
            }
        }
        #endregion
    }

and:

    public class WeakCollectionChangedListener
    {
        #region Private Fields
        private INotifyCollectionChanged _source;
        private WeakReference _handler;
        #endregion

        #region Ctor
        public WeakCollectionChangedListener(INotifyCollectionChanged source, NotifyCollectionChangedEventHandler handler)
        {
            this._source = source;
            this._source.CollectionChanged += this.OnCollectionChanged;
            this._handler = new WeakReference(handler);
        }
        #endregion

        #region Public Methods
        public static WeakCollectionChangedListener Create(INotifyCollectionChanged source, NotifyCollectionChangedEventHandler handler)
        {
            return new WeakCollectionChangedListener(source, handler);
        }

        public void Disconnect()
        {
            if (_source != null)
            {
                _source.CollectionChanged -= this.OnCollectionChanged;
                _source = null;
                _handler = null;
            }
        }
        #endregion

        #region Private Methods
        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_handler != null)
            {
                var handler = _handler.Target as NotifyCollectionChangedEventHandler;
                if (handler != null)
                {
                    handler(sender, e);
                }
                else
                {
                    this.Disconnect();
                }
            }
        }
        #endregion
    }

 Then you simple subscribe like this:

WeakPropertyChangedListener.Create(person, OnPersonPropertyChanged);

WeakCollectionChangedListener.Create(person.Children, OnPersonCollectionChanged);

Safe in the knowledge that your observing the notifications will not cause your domain objects to hang around.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: