PropertyChangedEventManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Base / System / ComponentModel / PropertyChangedEventManager.cs / 1 / PropertyChangedEventManager.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Manager for the PropertyChanged event in the "weak event listener" 
//              pattern.  See WeakEventTable.cs for an overview. 
//
//--------------------------------------------------------------------------- 

using System;
using System.Collections;       // ICollection
using System.Collections.Specialized;   // HybridDictionary 
using System.ComponentModel;    // INotifyPropertyChanged
using System.Diagnostics;       // Debug 
using System.Windows;           // WeakEventManager 

namespace System.ComponentModel 
{
    /// 
    /// Manager for the INotifyPropertyChanged.PropertyChanged event.
    ///  
    public class PropertyChangedEventManager : WeakEventManager
    { 
        #region Constructors 

        // 
        //  Constructors
        //

        private PropertyChangedEventManager() 
        {
        } 
 
        #endregion Constructors
 
        #region Public Methods

        //
        //  Public Methods 
        //
 
        ///  
        /// Add a listener to the given source's event.
        ///  
        public static void AddListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName)
        {
            CurrentManager.PrivateAddListener(source, listener, propertyName);
        } 

        ///  
        /// Remove a listener to the given source's event. 
        /// 
        public static void RemoveListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName) 
        {
            CurrentManager.PrivateRemoveListener(source, listener, propertyName);
        }
 
        #endregion Public Methods
 
        #region Protected Methods 

        // 
        //  Protected Methods
        //

        ///  
        /// Listen to the given source for the event.
        ///  
        protected override void StartListening(object source) 
        {
            INotifyPropertyChanged typedSource = (INotifyPropertyChanged)source; 
            typedSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
        }

        ///  
        /// Stop listening to the given source for the event.
        ///  
        protected override void StopListening(object source) 
        {
            INotifyPropertyChanged typedSource = (INotifyPropertyChanged)source; 
            typedSource.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyChanged);
        }

        ///  
        /// Remove dead entries from the data for the given source.   Returns true if
        /// some entries were actually removed. 
        ///  
        protected override bool Purge(object source, object data, bool purgeAll)
        { 
            bool foundDirt = false;

            if (!purgeAll)
            { 
                HybridDictionary dict = (HybridDictionary)data;
 
                // copy the keys into a separate array, so that later on 
                // we can change the dictionary while iterating over the keys
                ICollection ic = dict.Keys; 
                String[] keys = new String[ic.Count];
                ic.CopyTo(keys, 0);

                for (int i=keys.Length-1; i>=0; --i) 
                {
                    if (keys[i] == AllListenersKey) 
                        continue;       // ignore the special entry for now 

                    // for each key, remove dead entries in its list 
                    bool removeList = purgeAll || source == null;

                    if (!removeList)
                    { 
                        ListenerList list = (ListenerList)dict[keys[i]];
 
                        if (ListenerList.PrepareForWriting(ref list)) 
                            dict[keys[i]] = list;
 
                        if (list.Purge())
                            foundDirt = true;

                        removeList = (list.IsEmpty); 
                    }
 
                    // if there are no more entries, remove the key 
                    if (removeList)
                    { 
                        dict.Remove(keys[i]);
                    }
                }
 
                if (dict.Count == 0)
                { 
                    // if there are no more listeners at all, remove the entry from 
                    // the main table, and prepare to stop listening
                    purgeAll = true; 
                    if (source != null)     // source may have been GC'd
                    {
                        this.Remove(source);
                    } 
                }
                else if (foundDirt) 
                { 
                    // if any entries were purged, invalidate the special entry
                    dict.Remove(AllListenersKey); 
                }
            }

            if (purgeAll) 
            {
                // stop listening.  List cleanup is handled by Purge() 
                if (source != null) // source may have been GC'd 
                {
                    StopListening(source); 
                }
                foundDirt = true;
            }
 
            return foundDirt;
        } 
 
        #endregion Protected Methods
 
        #region Private Properties

        //
        //  Private Properties 
        //
 
        // get the event manager for the current thread 
        private static PropertyChangedEventManager CurrentManager
        { 
            get
            {
                Type managerType = typeof(PropertyChangedEventManager);
                PropertyChangedEventManager manager = (PropertyChangedEventManager)GetCurrentManager(managerType); 

                // at first use, create and register a new manager 
                if (manager == null) 
                {
                    manager = new PropertyChangedEventManager(); 
                    SetCurrentManager(managerType, manager);
                }

                return manager; 
            }
        } 
 
        #endregion Private Properties
 
        #region Private Methods

        //
        //  Private Methods 
        //
 
        // PropertyChanged is a special case - we superimpose per-property granularity 
        // on top of this event, by keeping separate lists of listeners for
        // each property. 

        // Add a listener to the named property (empty means "any property")
        private void PrivateAddListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName)
        { 
            Debug.Assert(listener != null && source != null && propertyName != null,
                "Listener, source, and propertyName of event cannot be null"); 
 
            using (WriteLock)
            { 
                HybridDictionary dict = (HybridDictionary)this[source];

                if (dict == null)
                { 
                    // no entry in the hashtable - add a new one
                    dict = new HybridDictionary(true /* case insensitive */); 
 
                    this[source] = dict;
 
                    // listen for the desired events
                    StartListening(source);
                }
 
                ListenerList list = (ListenerList)dict[propertyName];
 
                if (list == null) 
                {
                    // no entry in the dictionary - add a new one 
                    list = new ListenerList();

                    dict[propertyName] = list;
                } 

                // make sure list is ready for writing 
                if (ListenerList.PrepareForWriting(ref list)) 
                {
                    dict[propertyName] = list; 
                }

                // add a listener to the list
                list.Add(listener); 
                dict.Remove(AllListenersKey);   // invalidate list of all listeners
 
                // schedule a cleanup pass 
                ScheduleCleanup();
            } 
        }

        // Remove a listener to the named property (empty means "any property")
        private void PrivateRemoveListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName) 
        {
            Debug.Assert(listener != null && source != null && propertyName != null, 
                "Listener, source, and propertyName of event cannot be null"); 

            using (WriteLock) 
            {
                HybridDictionary dict = (HybridDictionary)this[source];

                if (dict != null) 
                {
                    ListenerList list = (ListenerList)dict[propertyName]; 
 
                    if (list != null)
                    { 
                        // make sure list is ready for writing
                        if (ListenerList.PrepareForWriting(ref list))
                        {
                            dict[propertyName] = list; 
                        }
 
                        // remove a listener from the list 
                        list.Remove(listener);
 
                        // when the last listener goes away, remove the list
                        if (list.IsEmpty)
                        {
                            dict.Remove(propertyName); 
                        }
                    } 
 
                    if (dict.Count == 0)
                    { 
                        StopListening(source);

                        Remove(source);
                    } 

                    dict.Remove(AllListenersKey);   // invalidate list of all listeners 
                } 
            }
        } 

        // event handler for PropertyChanged event
        private void OnPropertyChanged(object sender, PropertyChangedEventArgs args)
        { 
            ListenerList list;
            string propertyName = args.PropertyName; 
 
            // get the list of listeners
            using (ReadLock) 
            {
                // look up the list of listeners
                HybridDictionary dict = (HybridDictionary)this[sender];
 
                if (dict == null)
                { 
                    // this can happen when the last listener stops listening, but the 
                    // source raises the event on another thread after the dictionary
                    // has been removed (bug 1235351) 
                    list = ListenerList.Empty;
                }
                else if (!String.IsNullOrEmpty(propertyName))
                { 
                    // source has changed a particular property.  Notify targets
                    // who are listening either for this property or for all properties. 
                    ListenerList listeners = (ListenerList)dict[propertyName]; 
                    ListenerList genericListeners = (ListenerList)dict[String.Empty];
 
                    if (genericListeners == null)
                    {
                        if (listeners != null)
                        { 
                            list = listeners;           // only specific listeners
                        } 
                        else 
                        {
                            list = ListenerList.Empty;  // no listeners at all 
                        }
                    }
                    else
                    { 
                        if (listeners != null)
                        { 
                            // there are both specific and generic listeners - 
                            // combine the two lists.
                            list = new ListenerList(listeners.Count + genericListeners.Count); 
                            for (int i=0, n=listeners.Count; i
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Manager for the PropertyChanged event in the "weak event listener" 
//              pattern.  See WeakEventTable.cs for an overview. 
//
//--------------------------------------------------------------------------- 

using System;
using System.Collections;       // ICollection
using System.Collections.Specialized;   // HybridDictionary 
using System.ComponentModel;    // INotifyPropertyChanged
using System.Diagnostics;       // Debug 
using System.Windows;           // WeakEventManager 

namespace System.ComponentModel 
{
    /// 
    /// Manager for the INotifyPropertyChanged.PropertyChanged event.
    ///  
    public class PropertyChangedEventManager : WeakEventManager
    { 
        #region Constructors 

        // 
        //  Constructors
        //

        private PropertyChangedEventManager() 
        {
        } 
 
        #endregion Constructors
 
        #region Public Methods

        //
        //  Public Methods 
        //
 
        ///  
        /// Add a listener to the given source's event.
        ///  
        public static void AddListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName)
        {
            CurrentManager.PrivateAddListener(source, listener, propertyName);
        } 

        ///  
        /// Remove a listener to the given source's event. 
        /// 
        public static void RemoveListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName) 
        {
            CurrentManager.PrivateRemoveListener(source, listener, propertyName);
        }
 
        #endregion Public Methods
 
        #region Protected Methods 

        // 
        //  Protected Methods
        //

        ///  
        /// Listen to the given source for the event.
        ///  
        protected override void StartListening(object source) 
        {
            INotifyPropertyChanged typedSource = (INotifyPropertyChanged)source; 
            typedSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
        }

        ///  
        /// Stop listening to the given source for the event.
        ///  
        protected override void StopListening(object source) 
        {
            INotifyPropertyChanged typedSource = (INotifyPropertyChanged)source; 
            typedSource.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyChanged);
        }

        ///  
        /// Remove dead entries from the data for the given source.   Returns true if
        /// some entries were actually removed. 
        ///  
        protected override bool Purge(object source, object data, bool purgeAll)
        { 
            bool foundDirt = false;

            if (!purgeAll)
            { 
                HybridDictionary dict = (HybridDictionary)data;
 
                // copy the keys into a separate array, so that later on 
                // we can change the dictionary while iterating over the keys
                ICollection ic = dict.Keys; 
                String[] keys = new String[ic.Count];
                ic.CopyTo(keys, 0);

                for (int i=keys.Length-1; i>=0; --i) 
                {
                    if (keys[i] == AllListenersKey) 
                        continue;       // ignore the special entry for now 

                    // for each key, remove dead entries in its list 
                    bool removeList = purgeAll || source == null;

                    if (!removeList)
                    { 
                        ListenerList list = (ListenerList)dict[keys[i]];
 
                        if (ListenerList.PrepareForWriting(ref list)) 
                            dict[keys[i]] = list;
 
                        if (list.Purge())
                            foundDirt = true;

                        removeList = (list.IsEmpty); 
                    }
 
                    // if there are no more entries, remove the key 
                    if (removeList)
                    { 
                        dict.Remove(keys[i]);
                    }
                }
 
                if (dict.Count == 0)
                { 
                    // if there are no more listeners at all, remove the entry from 
                    // the main table, and prepare to stop listening
                    purgeAll = true; 
                    if (source != null)     // source may have been GC'd
                    {
                        this.Remove(source);
                    } 
                }
                else if (foundDirt) 
                { 
                    // if any entries were purged, invalidate the special entry
                    dict.Remove(AllListenersKey); 
                }
            }

            if (purgeAll) 
            {
                // stop listening.  List cleanup is handled by Purge() 
                if (source != null) // source may have been GC'd 
                {
                    StopListening(source); 
                }
                foundDirt = true;
            }
 
            return foundDirt;
        } 
 
        #endregion Protected Methods
 
        #region Private Properties

        //
        //  Private Properties 
        //
 
        // get the event manager for the current thread 
        private static PropertyChangedEventManager CurrentManager
        { 
            get
            {
                Type managerType = typeof(PropertyChangedEventManager);
                PropertyChangedEventManager manager = (PropertyChangedEventManager)GetCurrentManager(managerType); 

                // at first use, create and register a new manager 
                if (manager == null) 
                {
                    manager = new PropertyChangedEventManager(); 
                    SetCurrentManager(managerType, manager);
                }

                return manager; 
            }
        } 
 
        #endregion Private Properties
 
        #region Private Methods

        //
        //  Private Methods 
        //
 
        // PropertyChanged is a special case - we superimpose per-property granularity 
        // on top of this event, by keeping separate lists of listeners for
        // each property. 

        // Add a listener to the named property (empty means "any property")
        private void PrivateAddListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName)
        { 
            Debug.Assert(listener != null && source != null && propertyName != null,
                "Listener, source, and propertyName of event cannot be null"); 
 
            using (WriteLock)
            { 
                HybridDictionary dict = (HybridDictionary)this[source];

                if (dict == null)
                { 
                    // no entry in the hashtable - add a new one
                    dict = new HybridDictionary(true /* case insensitive */); 
 
                    this[source] = dict;
 
                    // listen for the desired events
                    StartListening(source);
                }
 
                ListenerList list = (ListenerList)dict[propertyName];
 
                if (list == null) 
                {
                    // no entry in the dictionary - add a new one 
                    list = new ListenerList();

                    dict[propertyName] = list;
                } 

                // make sure list is ready for writing 
                if (ListenerList.PrepareForWriting(ref list)) 
                {
                    dict[propertyName] = list; 
                }

                // add a listener to the list
                list.Add(listener); 
                dict.Remove(AllListenersKey);   // invalidate list of all listeners
 
                // schedule a cleanup pass 
                ScheduleCleanup();
            } 
        }

        // Remove a listener to the named property (empty means "any property")
        private void PrivateRemoveListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName) 
        {
            Debug.Assert(listener != null && source != null && propertyName != null, 
                "Listener, source, and propertyName of event cannot be null"); 

            using (WriteLock) 
            {
                HybridDictionary dict = (HybridDictionary)this[source];

                if (dict != null) 
                {
                    ListenerList list = (ListenerList)dict[propertyName]; 
 
                    if (list != null)
                    { 
                        // make sure list is ready for writing
                        if (ListenerList.PrepareForWriting(ref list))
                        {
                            dict[propertyName] = list; 
                        }
 
                        // remove a listener from the list 
                        list.Remove(listener);
 
                        // when the last listener goes away, remove the list
                        if (list.IsEmpty)
                        {
                            dict.Remove(propertyName); 
                        }
                    } 
 
                    if (dict.Count == 0)
                    { 
                        StopListening(source);

                        Remove(source);
                    } 

                    dict.Remove(AllListenersKey);   // invalidate list of all listeners 
                } 
            }
        } 

        // event handler for PropertyChanged event
        private void OnPropertyChanged(object sender, PropertyChangedEventArgs args)
        { 
            ListenerList list;
            string propertyName = args.PropertyName; 
 
            // get the list of listeners
            using (ReadLock) 
            {
                // look up the list of listeners
                HybridDictionary dict = (HybridDictionary)this[sender];
 
                if (dict == null)
                { 
                    // this can happen when the last listener stops listening, but the 
                    // source raises the event on another thread after the dictionary
                    // has been removed (bug 1235351) 
                    list = ListenerList.Empty;
                }
                else if (!String.IsNullOrEmpty(propertyName))
                { 
                    // source has changed a particular property.  Notify targets
                    // who are listening either for this property or for all properties. 
                    ListenerList listeners = (ListenerList)dict[propertyName]; 
                    ListenerList genericListeners = (ListenerList)dict[String.Empty];
 
                    if (genericListeners == null)
                    {
                        if (listeners != null)
                        { 
                            list = listeners;           // only specific listeners
                        } 
                        else 
                        {
                            list = ListenerList.Empty;  // no listeners at all 
                        }
                    }
                    else
                    { 
                        if (listeners != null)
                        { 
                            // there are both specific and generic listeners - 
                            // combine the two lists.
                            list = new ListenerList(listeners.Count + genericListeners.Count); 
                            for (int i=0, n=listeners.Count; i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK