File: cdf\src\NetFx40\Tools\System.Activities.Presentation\System\Activities\Presentation\Base\Interaction\Model\ModelItemCollection.cs
Project: ndp\System.Data.csproj (System.Data)
//------------------------------------------------------------------------------
// <copyright file="ModelItemCollection.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
namespace System.Activities.Presentation.Model {
 
    using System.Activities.Presentation.Internal.Properties;
    using System.Activities.Presentation;
 
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Windows;
 
    /// <summary>
    /// ModelItemCollection derives from ModelItem and implements 
    /// support for a collection of items.  
    ///
    /// ModelItemCollection defines a static attached property called 
    /// Item.  This property is returned from the Properties 
    /// enumeration of the collection, in addition to any properties 
    /// defined on the collection.  The Item property represents all 
    /// the items in the collection and is defined as type 
    /// IEnumerable of ModelItem.  All items in the collection have 
    /// their Source property set to this property.  The property’s metadata 
    /// marks it non browsable and non-serializable.  The Item property is a 
    /// "pseudo" property because it is not actually set on the model.  The 
    /// value it points to is the ModelItemCollection itself.
    /// </summary>
    public abstract class ModelItemCollection : ModelItem, IList<ModelItem>, IList, INotifyCollectionChanged {
 
        /// <summary>
        /// Creates a new ModelItemCollection.
        /// </summary>
        protected ModelItemCollection() { }
 
        /// <summary>
        /// Returns the item at the given index.  Sets the item at the 
        /// given index to the given value.
        /// </summary>
        /// <param name="index">The zero-based index into the collection.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        /// <exception cref="IndexOutOfRangeException">if index is less than 0 or greater than or equal to count.</exception>
        public abstract ModelItem this[int index] { get; set; }
 
        /// <summary>
        /// Returns the count of items in the collection.
        /// </summary>
        public abstract int Count { get; }
 
        /// <summary>
        /// Returns true if the collection is a fixed size.  
        /// The default implementation returns true if the
        /// collection is read only.
        /// </summary>
        protected virtual bool IsFixedSize {
            get { return IsReadOnly; }
        }
 
        /// <summary>
        /// Returns true if the collection cannot be modified.
        /// </summary>
        public abstract bool IsReadOnly { get; }
 
        /// <summary>
        /// Protected access to ICollection.IsSynchronized.
        /// </summary>
        protected virtual bool IsSynchronized {
            get { return false; }
        }
 
        /// <summary>
        /// Protected access to the SyncRoot object used to synchronize
        /// this collection.  The default value returns "this".
        /// </summary>
        protected virtual object SyncRoot {
            get { return this; }
        }
 
        /// <summary>
        /// This event is raised when the contents of this collection change.
        /// </summary>
        public abstract event NotifyCollectionChangedEventHandler CollectionChanged;
 
        /// <summary>
        /// Adds the item to the collection. 
        /// </summary>
        /// <param name="item"></param>
        /// <exception cref="ArgumentNullException">if item is null.</exception>
        /// <exception cref="InvalidOperationException">if the collection is read only.</exception>
        public abstract void Add(ModelItem item);
 
        /// <summary>
        /// Adds the given value to the collection.  This will create an item
        /// for the value.  It returns the newly created item.
        /// </summary>
        /// <param name="value"></param>
        /// <returns>an item representing the value</returns>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        /// <exception cref="InvalidOperationException">if the collection is read only.</exception>
        public abstract ModelItem Add(object value);
 
        /// <summary>
        /// Clears the contents of the collection.
        /// </summary>
        /// <exception cref="InvalidOperationException">if the collection is read only.</exception>
        public abstract void Clear();
 
        /// <summary>
        /// Returns true if the collection contains the given item.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">if item is null.</exception>
        public abstract bool Contains(ModelItem item);
 
        /// <summary>
        /// Returns true if the collection contains the given value.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        public abstract bool Contains(object value);
 
        //
        // Helper method that verifies that objects can be upcast to
        // the correct type.
        //
        private static ModelItem ConvertType(object value) {
            try {
                return (ModelItem)value;
            }
            catch (InvalidCastException) {
                throw FxTrace.Exception.AsError(new ArgumentException(
                    string.Format(CultureInfo.CurrentCulture,
                        Resources.Error_ArgIncorrectType,
                        "value", typeof(ModelItem).FullName)));
 
            }
        }
 
        /// <summary>
        /// Copies the contents of the collection into the given array.
        /// </summary>
        /// <exception cref="ArgumentNullException">if array is null.</exception>
        /// <exception cref="IndexOutOfRangeException">
        /// if arrayIndex is outside the bounds of the items array or if there is 
        /// insuffient space in the array to hold the collection.
        /// </exception>
        public abstract void CopyTo(ModelItem[] array, int arrayIndex);
 
        /// <summary>
        /// Returns an enumerator for the items in the collection.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerator<ModelItem> GetEnumerator();
 
        /// <summary>
        /// Returns the index of the given item or -1 if the item does not exist.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">if item is null.</exception>
        public abstract int IndexOf(ModelItem item);
 
        /// <summary>
        /// Inserts the item at the given location.  To
        /// move an item, use Move.  If index is == Count this will insert the item 
        /// at the end.  If it is zero it will insert at the beginning.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        /// <exception cref="ArgumentNullException">if item is null.</exception>
        /// <exception cref="IndexOutOfRangeException">if index is less than 0 or greater than count.</exception>
        public abstract void Insert(int index, ModelItem item);
 
        /// <summary>
        /// Inserts the item at the given location.  To
        /// move an item, use Move.  If index is == Count this will insert the item 
        /// at the end.  If it is zero it will insert at the beginning.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        /// <returns>an item representing the value</returns>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        /// <exception cref="IndexOutOfRangeException">if index is less than 0 or greater than count.</exception>
        public abstract ModelItem Insert(int index, object value);
 
        /// <summary>
        /// Moves the item at fromIndex to toIndex.  The value for toIndex is 
        /// always where you want the item to be according to how the collection 
        /// currently sits.  This means that if you are moving an item to a higher 
        /// index you don’t have to account for the fact that the indexes will 
        /// shuffle when the item is removed from its current location.
        /// </summary>
        /// <param name="fromIndex">
        /// The index of the item to move.
        /// </param>
        /// <param name="toIndex">
        /// The index to move it to.
        /// </param>
        /// <exception cref="IndexOutOfRangeException">
        /// if fromIndex or toIndex is less than zero or greater than or
        /// equal to Count.
        /// </exception>
        public abstract void Move(int fromIndex, int toIndex);
 
        /// <summary>
        /// Removes the item from the collection.  This does nothing if the 
        /// item does not exist in the collection.
        /// </summary>
        /// <param name="item"></param>
        /// <exception cref="ArgumentNullException">if item is null.</exception>
        public abstract bool Remove(ModelItem item);
 
        /// <summary>
        /// Removes the value from the collection.  This does nothing if the 
        /// value does not exist in the collection.
        /// </summary>
        /// <param name="value"></param>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        public abstract bool Remove(object value);
 
        /// <summary>
        /// Removes the item at the given index.
        /// </summary>
        /// <param name="index"></param>
        /// <exception cref="IndexOutOfRangeException">if index is less than 0 or greater than or equal to count.</exception>
        public abstract void RemoveAt(int index);
 
        /// <summary>
        /// This property is returned from the Properties enumeration of 
        /// the collection, in addition to any properties defined on the 
        /// collection.  The Item property represents all the items in 
        /// the collection and is defined as type IEnumerable of ModelItem.  
        /// All items in the collection have their Source property set to 
        /// this property.  The property’s metadata marks it non browsable 
        /// and non-serializable.  The Item property is a "pseudo"property 
        /// because it is not actually set on the model.  The value it points 
        /// to is the ModelItemCollection itself.
        /// </summary>
        public static readonly DependencyProperty ItemProperty = DependencyProperty.RegisterAttachedReadOnly(
            "Item",
            typeof(IEnumerable<ModelItem>),
            typeof(ModelItemCollection), null).DependencyProperty;
 
        #region IList Members
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        int IList.Add(object value) {
            Add(value);
            return Count - 1;
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        void IList.Clear() {
            Clear();
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        bool IList.Contains(object value) {
            return Contains(value);
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        int IList.IndexOf(object value) {
            return IndexOf(ConvertType(value));
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        void IList.Insert(int index, object value) {
            Insert(index, value);
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        bool IList.IsFixedSize {
            get { return IsFixedSize; }
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        bool IList.IsReadOnly {
            get { return IsReadOnly; }
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        void IList.Remove(object value) {
            Remove(value);
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        void IList.RemoveAt(int index) {
            RemoveAt(index);
        }
 
        /// <summary>
        /// IList Implementation maps back to public API.
        /// </summary>
        object IList.this[int index] {
            get { return this[index]; }
            set { this[index] = ConvertType(value); }
        }
 
        #endregion
 
        #region ICollection Members
 
        /// <summary>
        /// ICollection Implementation maps back to public API.
        /// </summary>
        void ICollection.CopyTo(Array array, int index) {
            for (int idx = 0; idx < Count; idx++) {
                array.SetValue(this[idx], idx + index);
            }
        }
 
        /// <summary>
        /// ICollection Implementation maps back to public API.
        /// </summary>
        int ICollection.Count {
            get { return Count; }
        }
 
        /// <summary>
        /// ICollection Implementation maps back to public API.
        /// </summary>
        bool ICollection.IsSynchronized {
            get { return IsSynchronized; }
        }
 
        /// <summary>
        /// ICollection Implementation maps back to public API.
        /// </summary>
        object ICollection.SyncRoot {
            get { return SyncRoot; }
        }
 
        #endregion
 
        #region IEnumerable Members
 
        /// <summary>
        /// IEnumerable Implementation maps back to public API.
        /// </summary>
        IEnumerator IEnumerable.GetEnumerator() {
            foreach (object o in this) {
                yield return o;
            }
        }
 
        #endregion
    }
}