CompositeCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Data / CompositeCollection.cs / 1305600 / CompositeCollection.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: CompositeCollection holds the list of items that constitute the content of a ItemsControl. 
//
// See specs at http://avalon/connecteddata/Specs/ItemsControl.mht 
//
// History:
//  09/22/2003 : kenlai - moved from ItemCollection
// 
//---------------------------------------------------------------------------
 
 
using System.Collections;
using System.Collections.Specialized; 
using System.ComponentModel;

using System.Windows;
using System.Windows.Markup; 

using MS.Internal;              // Invariant.Assert 
using MS.Internal.Data; 
using MS.Utility;
 
using System;

namespace System.Windows.Data
{ 
    /// 
    /// CompositeCollection will contain items shaped as strings, objects, xml nodes, 
    /// elements as well as other collections. 
    /// A  uses the data
    /// in the CompositeCollection to generate its content according to its ItemTemplate. 
    /// 

    [Localizability(LocalizationCategory.Ignore)]
    public class CompositeCollection : IList, INotifyCollectionChanged, ICollectionViewFactory, IWeakEventListener 
    {
        //----------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-----------------------------------------------------

        #region Constructors
 
        /// 
        /// Initializes a new instance of CompositeCollection that is empty and has default initial capacity. 
        ///  
        public CompositeCollection()
        { 
            Initialize(new ArrayList());
        }

        ///  
        /// Initializes a new instance of CompositeCollection that is empty and has specified initial capacity.
        ///  
        /// The number of items that the new list is initially capable of storing 
        /// 
        /// Some ItemsControl implementations have better idea how many items to anticipate, 
        /// capacity parameter lets them tailor the initial size.
        /// 
        public CompositeCollection(int capacity)
        { 
            Initialize(new ArrayList(capacity));
        } 
 
        #endregion Constructors
 

        //------------------------------------------------------
        //
        //  Public Methods 
        //
        //----------------------------------------------------- 
 
        #region Public Methods
        ///  
        ///     Returns an enumerator object for this CompositeCollection
        /// 
        /// 
        ///     Enumerator object for this CompositeCollection 
        /// 
        IEnumerator IEnumerable.GetEnumerator() 
        { 
            // Enumerator from the underlying ArrayList
            return InternalList.GetEnumerator(); 
        }

        /// 
        ///     Makes a shallow copy of object references from this 
        ///     CompositeCollection to the given target array
        ///  
        ///  
        ///     Target of the copy operation
        ///  
        /// 
        ///     Zero-based index at which the copy begins
        /// 
        public void CopyTo(Array array, int index) 
        {
            // Forward call to internal list. 
            InternalList.CopyTo(array, index); 
        }
 
        /// 
        ///     Add an item to this collection.
        /// 
        ///  
        ///     New item to be added to collection
        ///  
        ///  
        ///     Zero-based index where the new item is added.
        ///  
        /// 
        ///     CompositeCollection can only accept CollectionContainers it doesn't already have.
        /// 
        public int Add(object newItem) 
        {
            CollectionContainer cc = newItem as CollectionContainer; 
            if (cc != null) 
            {
                AddCollectionContainer(cc); 
            }

            int addedIndex = InternalList.Add(newItem);
 
            OnCollectionChanged(NotifyCollectionChangedAction.Add, newItem, addedIndex);
            return addedIndex; 
        } 

        ///  
        ///     Clears the collection.  Releases the references on all items
        /// currently in the collection.
        /// 
        public void Clear() 
        {
            // unhook contained collections 
            for (int k=0, n=InternalList.Count;  k < n;  ++k) 
            {
                CollectionContainer cc = this[k] as CollectionContainer; 
                if (cc != null)
                {
                    RemoveCollectionContainer(cc);
                } 
            }
 
            InternalList.Clear(); 
            OnCollectionChanged(NotifyCollectionChangedAction.Reset);
        } 

        /// 
        ///     Checks to see if a given item is in this collection
        ///  
        /// 
        ///     The item whose membership in this collection is to be checked. 
        ///  
        /// 
        ///     True if the collection contains the given item 
        /// 
        public bool Contains(object containItem)
        {
            return InternalList.Contains(containItem); 
        }
 
        ///  
        ///     Finds the index in this collection where the given item is found.
        ///  
        /// 
        ///     The item whose index in this collection is to be retrieved.
        /// 
        ///  
        ///     Zero-based index into the collection where the given item can be
        /// found.  Otherwise, -1 
        ///  
        public int IndexOf(object indexItem)
        { 
            return InternalList.IndexOf(indexItem);
        }

        ///  
        ///     Insert an item in the collection at a given index.  All items
        /// after the given position are moved down by one. 
        ///  
        /// 
        ///     The index at which to inser the item 
        /// 
        /// 
        ///     The item reference to be added to the collection
        ///  
        /// 
        /// Thrown if index is out of range 
        ///  
        public void Insert(int insertIndex, object insertItem)
        { 
            CollectionContainer cc = insertItem as CollectionContainer;
            if (cc != null)
            {
                AddCollectionContainer(cc); 
            }
 
            // ArrayList implementation checks index and will throw out of range exception 
            InternalList.Insert(insertIndex, insertItem);
 
            OnCollectionChanged(NotifyCollectionChangedAction.Add, insertItem, insertIndex);
        }

        ///  
        ///     Removes the given item reference from the collection.  All
        /// remaining items move up by one. 
        ///  
        /// 
        ///     The item to be removed. 
        /// 
        public void Remove(object removeItem)
        {
            int index = InternalList.IndexOf(removeItem); 
            if (index >= 0)
            { 
                // to ensure model parent is cleared and the CollectionChange notification is raised, 
                // call this.RemoveAt, not the aggregated ArrayList
                this.RemoveAt(index); 
            }
        }

        ///  
        ///     Removes an item from the collection at the given index.  All
        /// remaining items move up by one. 
        ///  
        /// 
        ///     The index at which to remove an item. 
        /// 
        /// 
        /// Thrown if index is out of range
        ///  
        public void RemoveAt(int removeIndex)
        { 
            if ((0 <= removeIndex) && (removeIndex < Count)) 
            {
                object removedItem = this[removeIndex]; 

                CollectionContainer cc = removedItem as CollectionContainer;
                if (cc != null)
                { 
                    RemoveCollectionContainer(cc);
                } 
 
                InternalList.RemoveAt(removeIndex);
 
                OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, removeIndex);
            }
            else
            { 
                throw new ArgumentOutOfRangeException("removeIndex",
                            SR.Get(SRID.ItemCollectionRemoveArgumentOutOfRange)); 
            } 
        }
 

        /// 
        /// Create a new view on this collection [Do not call directly].
        ///  
        /// 
        /// Normally this method is only called by the platform's view manager, 
        /// not by user code. 
        /// 
        ICollectionView ICollectionViewFactory.CreateView() 
        {
            return new CompositeCollectionView(this);
        }
 
        #endregion Public Methods
 
 
        //------------------------------------------------------
        // 
        //  Public Properties
        //
        //------------------------------------------------------
 
        #region Public Properties
 
        ///  
        ///     Read-only property for the number of items stored in this collection of objects
        ///  
        /// 
        ///     CollectionContainers each count as 1 item.
        ///     When in ItemsSource mode, Count always equals 1.
        ///  
        public int Count
        { 
            get 
            {
                // Return value from the underlying ArrayList. 
                return InternalList.Count;
            }
        }
 
        /// 
        ///     Indexer property to retrieve or replace the item at the given 
        /// zero-based offset into the collection. 
        /// 
        ///  
        /// Thrown if index is out of range
        /// 
        public object this[int itemIndex]
        { 
            get
            { 
                // ArrayList implementation checks index and will throw out of range exception 
                return InternalList[itemIndex];
            } 
            set
            {
                // ArrayList implementation checks index and will throw out of range exception
                object originalItem = InternalList[itemIndex]; 

                // unhook the old, hook the new 
                CollectionContainer cc; 
                if ((cc = originalItem as CollectionContainer) != null)
                { 
                    RemoveCollectionContainer(cc);
                }
                if ((cc = value as CollectionContainer) != null)
                { 
                    AddCollectionContainer(cc);
                } 
 
                // make the change
                InternalList[itemIndex] = value; 

                OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, value, itemIndex);
            }
        } 

        ///  
        ///     Gets a value indicating whether access to the CompositeCollection is synchronized (thread-safe). 
        /// 
        bool ICollection.IsSynchronized 
        {
            get
            {
                // Return value from the underlying ArrayList. 
                return InternalList.IsSynchronized;
            } 
        } 

        ///  
        ///     Returns an object to be used in thread synchronization.
        /// 
        object ICollection.SyncRoot
        { 
            get
            { 
                // Return the SyncRoot object of the underlying ArrayList 
                return InternalList.SyncRoot;
            } 
        }

        /// 
        ///     Gets a value indicating whether the IList has a fixed size. 
        ///     An CompositeCollection can usually grow dynamically,
        ///     this call will commonly return FixedSize = False. 
        ///     In ItemsSource mode, this call will return IsFixedSize = True. 
        /// 
        bool IList.IsFixedSize 
        {
            get
            {
                return InternalList.IsFixedSize; 
            }
        } 
 
        /// 
        ///     Gets a value indicating whether the IList is read-only. 
        ///     An CompositeCollection is usually writable,
        ///     this call will commonly return IsReadOnly = False.
        ///     In ItemsSource mode, this call will return IsReadOnly = True.
        ///  
        bool IList.IsReadOnly
        { 
            get 
            {
                return InternalList.IsReadOnly; 
            }
        }

        #endregion Public Properties 

 
        //----------------------------------------------------- 
        //
        //  Public Events 
        //
        //------------------------------------------------------

        #region Public Events 

        ///  
        /// Occurs when the collection changes, either by adding or removing an item 
        /// 
        ///  
        event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
        {
            add
            { 
                CollectionChanged += value;
            } 
            remove 
            {
                CollectionChanged -= value; 
            }
        }

        ///  
        /// Occurs when the collection changes, either by adding or removing an item.
        ///  
        protected event NotifyCollectionChangedEventHandler CollectionChanged; 

        #endregion Public Events 

        #region IWeakEventListener

        ///  
        /// Handle events from the centralized event table
        ///  
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        {
            return ReceiveWeakEvent(managerType, sender, e); 
        }

        /// 
        /// Handle events from the centralized event table 
        /// 
        protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        { 
            if (managerType == typeof(CollectionChangedEventManager))
            { 
                // A CollectionContainer has raised a change event.  Forward
                // it to the CompositeCollectionView(s).
                OnContainedCollectionChanged(sender, (NotifyCollectionChangedEventArgs)e);
            } 
            else
            { 
                return false;       // unrecognized event 
            }
 
            return true;
        }

        #endregion IWeakEventListener 

        //----------------------------------------------------- 
        // 
        //  Internal Events
        // 
        //-----------------------------------------------------

        #region Internal Events
 
        internal event NotifyCollectionChangedEventHandler ContainedCollectionChanged;
 
        private void OnContainedCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
        {
            if (ContainedCollectionChanged != null) 
                ContainedCollectionChanged(sender, e);
        }

        #endregion Internal Events 

        //----------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //------------------------------------------------------

        #region Private Methods
 
        // common ctor initialization
        private void Initialize(ArrayList internalList) 
        { 
            _internalList = internalList;
        } 

        // ArrayList that holds collection containers as well as single items
        private ArrayList InternalList
        { 
            get
            { 
                return _internalList; 
            }
        } 

        // Hook up to a newly-added CollectionContainer
        private void AddCollectionContainer(CollectionContainer cc)
        { 
            if (InternalList.Contains(cc))
                throw new ArgumentException(SR.Get(SRID.CollectionContainerMustBeUniqueForComposite), "cc"); 
 
            CollectionChangedEventManager.AddListener(cc, this);
 
#if DEBUG
            _hasRepeatedCollectionIsValid = false;
#endif
        } 

        // Unhook a newly-deleted CollectionContainer 
        private void RemoveCollectionContainer(CollectionContainer cc) 
        {
            CollectionChangedEventManager.RemoveListener(cc, this); 

#if DEBUG
            _hasRepeatedCollectionIsValid = false;
#endif 
        }
 
        // raise CollectionChanged event to any listeners 
        void OnCollectionChanged(NotifyCollectionChangedAction action)
        { 
#if DEBUG
            _hasRepeatedCollectionIsValid = false;
#endif
 
            if (CollectionChanged != null)
            { 
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action)); 
            }
        } 

        // raise CollectionChanged event to any listeners
        void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
        { 
            if (CollectionChanged != null)
            { 
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item, index)); 
            }
        } 

        /// raise CollectionChanged event to any listeners
        void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
        { 
            if (CollectionChanged != null)
            { 
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); 
            }
        } 

        #endregion Private Methods

 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //------------------------------------------------------ 

        #region Private Fields

        private ArrayList               _internalList; 

        #endregion Private Fields 
 

        //------------------------------------------------------ 
        //
        //  Debugging Aids
        //
        //----------------------------------------------------- 

        #region Debugging Aids 
 
#if DEBUG
        internal bool HasRepeatedCollection() 
        {
            if (!_hasRepeatedCollectionIsValid)
            {
                _hasRepeatedCollection = FindRepeatedCollection(new ArrayList()); 
                _hasRepeatedCollectionIsValid = true;
            } 
            return _hasRepeatedCollection; 
        }
 
        // recursive depth-first search for repeated collection
        private bool FindRepeatedCollection(ArrayList collections)
        {
            for (int i = 0; i < Count; ++i) 
            {
                CollectionContainer cc = this[i] as CollectionContainer; 
                if (cc != null && cc.Collection != null) 
                {
                    CompositeCollection composite = cc.Collection as CompositeCollection; 
                    if (composite != null)
                    {
                        if (composite.FindRepeatedCollection(collections))
                            return true; 
                    }
                    else if (collections.IndexOf(cc.Collection) > -1) 
                        return true; 
                    else
                        collections.Add(cc.Collection); 
                }
            }
            return false;
        } 

        private bool _hasRepeatedCollection = false; 
        private bool _hasRepeatedCollectionIsValid = false; 
#endif
 
        #endregion Debugging Aids

    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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