ObjectView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Objects / ObjectView.cs / 1 / ObjectView.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       jhutson
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata; 
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses; 
using System.Diagnostics; 
using System.Reflection;
 
namespace System.Data.Objects
{
    /// 
    /// Manages a list suitable for data binding. 
    /// 
    ///  
    /// The type of elements in the binding list. 
    /// 
    ///  
    /// 
    /// This class provides an implementation of IBindingList that exposes a list of elements to be bound,
    /// provides a mechanism to change the membership of the list,
    /// and events to notify interested objects when the membership of the list is modified 
    /// or an element in the list is modified.
    ///  
    ///  
    /// ObjectView relies on an object that implements IObjectViewData to manage the binding list.
    /// See the documentation for IObjectViewData for details. 
    /// 
    /// 
    internal class ObjectView : IBindingList, ICancelAddNew, IObjectView
    { 
        /// 
        /// Specifies whether events handled from an underlying collection or individual bound item 
        /// should result in list change events being fired from this IBindingList. 
        /// True to prevent events from being fired from this IBindingList;
        /// otherwise false to allow events to propogate. 
        /// 
        private bool _suspendEvent;

        // Delegate for IBindingList.ListChanged event. 
        private ListChangedEventHandler onListChanged;
 
        ///  
        /// Object that listens for underlying collection or individual bound item changes,
        /// and notifies this object when they occur. 
        /// 
        private ObjectViewListener _listener;

        ///  
        /// Index of last item added via a call to IBindingList.AddNew.
        ///  
        private int _addNewIndex = -1; 

        ///  
        /// Object that maintains the underlying bound list,
        /// and specifies the operations allowed on that list.
        /// 
        private IObjectViewData _viewData; 

        ///  
        /// Construct a new instance of ObjectView using the supplied IObjectViewData and event data source. 
        /// 
        ///  
        /// Object that maintains the underlying bound list,
        /// and specifies the operations allowed on that list.
        /// 
        ///  
        /// Event source to "attach" to in order to listen to collection and item changes.
        ///  
        internal ObjectView(IObjectViewData viewData, object eventDataSource) 
        {
            _viewData = viewData; 
            _listener = new ObjectViewListener(this, (IList)_viewData.List, eventDataSource);
        }

        private void EnsureWritableList() 
        {
            if (((IList)this).IsReadOnly) 
            { 
                throw EntityUtil.WriteOperationNotAllowedOnReadOnlyBindingList();
            } 
        }

        private bool IsElementTypeAbstract
        { 
            get { return typeof(TElement).IsAbstract; }
        } 
 
        #region ICancelAddNew implementation
 
        /// 
        /// If a new item has been added to the list, and  is the position of that item,
        /// remove it from the list and cancel the add operation.
        ///  
        /// Index of item to be removed as a result of the cancellation of a previous addition.
        void ICancelAddNew.CancelNew(int itemIndex) 
        { 
            if (_addNewIndex >= 0 && itemIndex == _addNewIndex)
            { 
                TElement item = _viewData.List[_addNewIndex];
                _listener.UnregisterEntityEvents(item);

                int oldIndex = _addNewIndex; 

                // Reset the addNewIndex here so that the IObjectView.CollectionChanged method 
                // will not attempt to examine the item being removed. 
                // See IObjectView.CollectionChanged method for details.
                _addNewIndex = -1; 

                try
                {
                    _suspendEvent = true; 

                    _viewData.Remove(item, true); 
                } 
                finally
                { 
                    _suspendEvent = false;
                }

                OnListChanged(ListChangedType.ItemDeleted, oldIndex, -1); 
            }
        } 
 
        /// 
        /// Commit a new item to the binding list. 
        /// 
        /// 
        /// Index of item to be committed.
        /// This index must match the index of the item created by the last call to IBindindList.AddNew; 
        /// otherwise this method is a nop.
        ///  
        void ICancelAddNew.EndNew(int itemIndex) 
        {
            if (_addNewIndex >= 0 && itemIndex == _addNewIndex) 
            {
                _viewData.CommitItemAt(_addNewIndex);
                _addNewIndex = -1;
            } 
        }
        #endregion 
 

        #region IBindingList implementation 

        bool IBindingList.AllowNew
        {
            get { return _viewData.AllowNew && !IsElementTypeAbstract; } 
        }
 
        bool IBindingList.AllowEdit 
        {
            get { return _viewData.AllowEdit; } 
        }

        object IBindingList.AddNew()
        { 
            EnsureWritableList();
 
            if (IsElementTypeAbstract) 
            {
                throw EntityUtil.AddNewOperationNotAllowedOnAbstractBindingList(); 
            }

            _viewData.EnsureCanAddNew();
 
            ((ICancelAddNew)this).EndNew(_addNewIndex);
 
            TElement newItem = (TElement)Activator.CreateInstance(typeof(TElement)); 

            _addNewIndex = _viewData.Add(newItem, true); 

            _listener.RegisterEntityEvents(newItem);
            OnListChanged(ListChangedType.ItemAdded, _addNewIndex /* newIndex*/, -1 /*oldIndex*/);
 
            return newItem;
        } 
 
        bool IBindingList.AllowRemove
        { 
            get { return _viewData.AllowRemove; }
        }

        bool IBindingList.SupportsChangeNotification 
        {
            get { return true; } 
        } 

        bool IBindingList.SupportsSearching 
        {
            get { return false; }
        }
 
        bool IBindingList.SupportsSorting
        { 
            get { return false; } 
        }
 
        bool IBindingList.IsSorted
        {
            get { return false; }
        } 

        PropertyDescriptor IBindingList.SortProperty 
        { 
            get { throw EntityUtil.NotSupported(); }
        } 

        ListSortDirection IBindingList.SortDirection
        {
            get { throw EntityUtil.NotSupported(); } 
        }
 
        public event System.ComponentModel.ListChangedEventHandler ListChanged 
        {
            add 
            {
                onListChanged += value;
            }
            remove 
            {
                onListChanged -= value; 
            } 
        }
 
        void IBindingList.AddIndex(PropertyDescriptor property)
        {
            throw EntityUtil.NotSupported();
        } 

        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) 
        { 
            throw EntityUtil.NotSupported();
        } 

        int IBindingList.Find(PropertyDescriptor property, object key)
        {
            throw EntityUtil.NotSupported(); 
        }
 
        void IBindingList.RemoveIndex(PropertyDescriptor property) 
        {
            throw EntityUtil.NotSupported(); 
        }

        void IBindingList.RemoveSort()
        { 
            throw EntityUtil.NotSupported();
        } 
 
        #endregion
 
        /// 
        /// Get item at the specified index.
        /// 
        ///  
        /// The zero-based index of the element to get or set.
        ///  
        ///  
        /// This strongly-typed indexer is used by the data binding in WebForms and ASP.NET
        /// to determine the Type of elements in the bound list. 
        /// The list of properties available for binding can then be determined from that element Type.
        /// 
        public TElement this[int index]
        { 
            get
            { 
                return _viewData.List[index]; 
            }
            set 
            {
                // this represents a ROW basically whole entity, we should not allow any setting
                throw EntityUtil.CannotReplacetheEntityorRow();
            } 
        }
 
        #region IList implementation 

        object IList.this[int index] 
        {
            get
            {
                return _viewData.List[index]; 
            }
            set 
            { 
                // this represents a ROW basically whole entity, we should not allow any setting
                throw EntityUtil.CannotReplacetheEntityorRow(); 
            }
        }

        bool IList.IsReadOnly 
        {
            get 
            { 
                return !(_viewData.AllowNew || _viewData.AllowRemove);
            } 
        }

        bool IList.IsFixedSize
        { 
            get { return (false); }
        } 
 
        int IList.Add(object value)
        { 
            EnsureWritableList();

            EntityUtil.CheckArgumentNull(value, "value");
 
            if (!(value is TElement))
            { 
                throw EntityUtil.IncompatibleArgument(); 
            }
 
            ((ICancelAddNew)this).EndNew(_addNewIndex);

            int index = ((IList)this).IndexOf(value);
 
            // Add the item if it doesn't already exist in the binding list.
            if (index == -1) 
            { 
                index = _viewData.Add((TElement)value, false);
 
                // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself.
                if (!_viewData.FiresEventOnAdd)
                {
                    _listener.RegisterEntityEvents(value); 
                    OnListChanged(ListChangedType.ItemAdded, index /*newIndex*/, -1/* oldIndex*/);
                } 
            } 

            return index; 
        }

        void IList.Clear()
        { 
            EnsureWritableList();
 
            ((ICancelAddNew)this).EndNew(_addNewIndex); 

            // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself. 
            if (_viewData.FiresEventOnClear)
            {
                _viewData.Clear();
            } 
            else
            { 
                try 
                {
                    // Suspend list changed events during the clear, since the IObjectViewData declared that it wouldn't fire an event. 
                    // It's possible the IObjectViewData could implement Clear by repeatedly calling Remove,
                    // and we don't want these events to percolate during the Clear operation.
                    _suspendEvent = true;
                    _viewData.Clear(); 
                }
                finally 
                { 
                    _suspendEvent = false;
                } 

                OnListChanged(ListChangedType.Reset, -1 /*newIndex*/, -1/* oldIndex*/); // Indexes not used for reset event.
            }
        } 

        bool IList.Contains(object value) 
        { 
            bool itemExists;
 
            if (value is TElement)
            {
                itemExists = _viewData.List.Contains((TElement)value);
            } 
            else
            { 
                itemExists = false; 
            }
 
            return itemExists;
        }

        int IList.IndexOf(object value) 
        {
            int index; 
 
            if (value is TElement)
            { 
                index = _viewData.List.IndexOf((TElement)value);
            }
            else
            { 
                index = -1;
            } 
 
            return index;
        } 

        void IList.Insert(int index, object value)
        {
            throw EntityUtil.IndexBasedInsertIsNotSupported(); 
        }
 
        void IList.Remove(object value) 
        {
            EnsureWritableList(); 

            EntityUtil.CheckArgumentNull(value, "value");

            if (!(value is TElement)) 
            {
                throw EntityUtil.IncompatibleArgument(); 
            } 

            Debug.Assert(((IList)this).Contains(value), "Value does not exist in view."); 

            ((ICancelAddNew)this).EndNew(_addNewIndex);

            TElement item = (TElement)value; 

            int index = _viewData.List.IndexOf(item); 
            bool removed = _viewData.Remove(item, false); 

            // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself. 
            if (removed && !_viewData.FiresEventOnRemove)
            {
                _listener.UnregisterEntityEvents(item);
                OnListChanged(ListChangedType.ItemDeleted, index /* newIndex */, -1 /* oldIndex */); 
            }
        } 
 
        void IList.RemoveAt(int index)
        { 
            ((IList)this).Remove(((IList)this)[index]);
        }

        #endregion 

        #region  ICollection implementation 
 
        public int Count
        { 
            get { return _viewData.List.Count; }
        }

        public void CopyTo(Array array, int index) 
        {
            ((IList)_viewData.List).CopyTo(array, index); 
        } 

        object ICollection.SyncRoot 
        {
            get { return this; }
        }
 
        bool ICollection.IsSynchronized
        { 
            get { return false; } 
        }
 
        public IEnumerator GetEnumerator()
        {
            return _viewData.List.GetEnumerator();
        } 

        #endregion 
 
        private void OnListChanged(ListChangedType listchangedType, int newIndex, int oldIndex)
        { 
            ListChangedEventArgs changeArgs = new ListChangedEventArgs(listchangedType, newIndex, oldIndex);
            OnListChanged(changeArgs);
        }
 
        private void OnListChanged(ListChangedEventArgs changeArgs)
        { 
            // Only fire the event if someone listens to it and it is not suspended. 
            if (onListChanged != null && !_suspendEvent)
            { 
                onListChanged(this, changeArgs);
            }
        }
 
        void IObjectView.EntityPropertyChanged(object sender, PropertyChangedEventArgs e)
        { 
            Debug.Assert(sender is IEntityWithChangeTracker, "Should only receive events from IEntityWithChangeTracker objects."); 
            Debug.Assert(sender is TElement, "Entity should be of type TElement");
 
            int index = ((IList)this).IndexOf((TElement)sender);
            OnListChanged(ListChangedType.ItemChanged, index /*newIndex*/, index/*oldIndex*/);
        }
 
        /// 
        /// Handle a change in the underlying collection bound by this ObjectView. 
        ///  
        /// The source of the event.
        ///  
        /// Event arguments that specify the type of modification and the associated item.
        /// 
        void IObjectView.CollectionChanged(object sender, CollectionChangeEventArgs e)
        { 
            // If there is a pending edit of a new item in the bound list (indicated by _addNewIndex >= 0)
            // and the collection membership changed due to an operation external to this ObjectView, 
            // it is possible that the _addNewIndex position will need to be adjusted. 
            //
            // If the modification was made through this ObjectView, the pending edit would have been implicitly committed, 
            // and there would be no need to examine it here.
            TElement addNew = default(TElement);

            if (_addNewIndex >= 0) 
            {
                addNew = this[_addNewIndex]; 
            } 

            ListChangedEventArgs changeArgs = _viewData.OnCollectionChanged(sender, e, _listener); 

            if (_addNewIndex >= 0)
            {
                if (_addNewIndex >= this.Count) 
                {
                    _addNewIndex = ((IList)this).IndexOf(addNew); 
                } 
                else if (!this[_addNewIndex].Equals(addNew))
                { 
                    _addNewIndex = ((IList)this).IndexOf(addNew);
                }
            }
 
            if (changeArgs != null)
            { 
                OnListChanged(changeArgs); 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       jhutson
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata; 
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses; 
using System.Diagnostics; 
using System.Reflection;
 
namespace System.Data.Objects
{
    /// 
    /// Manages a list suitable for data binding. 
    /// 
    ///  
    /// The type of elements in the binding list. 
    /// 
    ///  
    /// 
    /// This class provides an implementation of IBindingList that exposes a list of elements to be bound,
    /// provides a mechanism to change the membership of the list,
    /// and events to notify interested objects when the membership of the list is modified 
    /// or an element in the list is modified.
    ///  
    ///  
    /// ObjectView relies on an object that implements IObjectViewData to manage the binding list.
    /// See the documentation for IObjectViewData for details. 
    /// 
    /// 
    internal class ObjectView : IBindingList, ICancelAddNew, IObjectView
    { 
        /// 
        /// Specifies whether events handled from an underlying collection or individual bound item 
        /// should result in list change events being fired from this IBindingList. 
        /// True to prevent events from being fired from this IBindingList;
        /// otherwise false to allow events to propogate. 
        /// 
        private bool _suspendEvent;

        // Delegate for IBindingList.ListChanged event. 
        private ListChangedEventHandler onListChanged;
 
        ///  
        /// Object that listens for underlying collection or individual bound item changes,
        /// and notifies this object when they occur. 
        /// 
        private ObjectViewListener _listener;

        ///  
        /// Index of last item added via a call to IBindingList.AddNew.
        ///  
        private int _addNewIndex = -1; 

        ///  
        /// Object that maintains the underlying bound list,
        /// and specifies the operations allowed on that list.
        /// 
        private IObjectViewData _viewData; 

        ///  
        /// Construct a new instance of ObjectView using the supplied IObjectViewData and event data source. 
        /// 
        ///  
        /// Object that maintains the underlying bound list,
        /// and specifies the operations allowed on that list.
        /// 
        ///  
        /// Event source to "attach" to in order to listen to collection and item changes.
        ///  
        internal ObjectView(IObjectViewData viewData, object eventDataSource) 
        {
            _viewData = viewData; 
            _listener = new ObjectViewListener(this, (IList)_viewData.List, eventDataSource);
        }

        private void EnsureWritableList() 
        {
            if (((IList)this).IsReadOnly) 
            { 
                throw EntityUtil.WriteOperationNotAllowedOnReadOnlyBindingList();
            } 
        }

        private bool IsElementTypeAbstract
        { 
            get { return typeof(TElement).IsAbstract; }
        } 
 
        #region ICancelAddNew implementation
 
        /// 
        /// If a new item has been added to the list, and  is the position of that item,
        /// remove it from the list and cancel the add operation.
        ///  
        /// Index of item to be removed as a result of the cancellation of a previous addition.
        void ICancelAddNew.CancelNew(int itemIndex) 
        { 
            if (_addNewIndex >= 0 && itemIndex == _addNewIndex)
            { 
                TElement item = _viewData.List[_addNewIndex];
                _listener.UnregisterEntityEvents(item);

                int oldIndex = _addNewIndex; 

                // Reset the addNewIndex here so that the IObjectView.CollectionChanged method 
                // will not attempt to examine the item being removed. 
                // See IObjectView.CollectionChanged method for details.
                _addNewIndex = -1; 

                try
                {
                    _suspendEvent = true; 

                    _viewData.Remove(item, true); 
                } 
                finally
                { 
                    _suspendEvent = false;
                }

                OnListChanged(ListChangedType.ItemDeleted, oldIndex, -1); 
            }
        } 
 
        /// 
        /// Commit a new item to the binding list. 
        /// 
        /// 
        /// Index of item to be committed.
        /// This index must match the index of the item created by the last call to IBindindList.AddNew; 
        /// otherwise this method is a nop.
        ///  
        void ICancelAddNew.EndNew(int itemIndex) 
        {
            if (_addNewIndex >= 0 && itemIndex == _addNewIndex) 
            {
                _viewData.CommitItemAt(_addNewIndex);
                _addNewIndex = -1;
            } 
        }
        #endregion 
 

        #region IBindingList implementation 

        bool IBindingList.AllowNew
        {
            get { return _viewData.AllowNew && !IsElementTypeAbstract; } 
        }
 
        bool IBindingList.AllowEdit 
        {
            get { return _viewData.AllowEdit; } 
        }

        object IBindingList.AddNew()
        { 
            EnsureWritableList();
 
            if (IsElementTypeAbstract) 
            {
                throw EntityUtil.AddNewOperationNotAllowedOnAbstractBindingList(); 
            }

            _viewData.EnsureCanAddNew();
 
            ((ICancelAddNew)this).EndNew(_addNewIndex);
 
            TElement newItem = (TElement)Activator.CreateInstance(typeof(TElement)); 

            _addNewIndex = _viewData.Add(newItem, true); 

            _listener.RegisterEntityEvents(newItem);
            OnListChanged(ListChangedType.ItemAdded, _addNewIndex /* newIndex*/, -1 /*oldIndex*/);
 
            return newItem;
        } 
 
        bool IBindingList.AllowRemove
        { 
            get { return _viewData.AllowRemove; }
        }

        bool IBindingList.SupportsChangeNotification 
        {
            get { return true; } 
        } 

        bool IBindingList.SupportsSearching 
        {
            get { return false; }
        }
 
        bool IBindingList.SupportsSorting
        { 
            get { return false; } 
        }
 
        bool IBindingList.IsSorted
        {
            get { return false; }
        } 

        PropertyDescriptor IBindingList.SortProperty 
        { 
            get { throw EntityUtil.NotSupported(); }
        } 

        ListSortDirection IBindingList.SortDirection
        {
            get { throw EntityUtil.NotSupported(); } 
        }
 
        public event System.ComponentModel.ListChangedEventHandler ListChanged 
        {
            add 
            {
                onListChanged += value;
            }
            remove 
            {
                onListChanged -= value; 
            } 
        }
 
        void IBindingList.AddIndex(PropertyDescriptor property)
        {
            throw EntityUtil.NotSupported();
        } 

        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) 
        { 
            throw EntityUtil.NotSupported();
        } 

        int IBindingList.Find(PropertyDescriptor property, object key)
        {
            throw EntityUtil.NotSupported(); 
        }
 
        void IBindingList.RemoveIndex(PropertyDescriptor property) 
        {
            throw EntityUtil.NotSupported(); 
        }

        void IBindingList.RemoveSort()
        { 
            throw EntityUtil.NotSupported();
        } 
 
        #endregion
 
        /// 
        /// Get item at the specified index.
        /// 
        ///  
        /// The zero-based index of the element to get or set.
        ///  
        ///  
        /// This strongly-typed indexer is used by the data binding in WebForms and ASP.NET
        /// to determine the Type of elements in the bound list. 
        /// The list of properties available for binding can then be determined from that element Type.
        /// 
        public TElement this[int index]
        { 
            get
            { 
                return _viewData.List[index]; 
            }
            set 
            {
                // this represents a ROW basically whole entity, we should not allow any setting
                throw EntityUtil.CannotReplacetheEntityorRow();
            } 
        }
 
        #region IList implementation 

        object IList.this[int index] 
        {
            get
            {
                return _viewData.List[index]; 
            }
            set 
            { 
                // this represents a ROW basically whole entity, we should not allow any setting
                throw EntityUtil.CannotReplacetheEntityorRow(); 
            }
        }

        bool IList.IsReadOnly 
        {
            get 
            { 
                return !(_viewData.AllowNew || _viewData.AllowRemove);
            } 
        }

        bool IList.IsFixedSize
        { 
            get { return (false); }
        } 
 
        int IList.Add(object value)
        { 
            EnsureWritableList();

            EntityUtil.CheckArgumentNull(value, "value");
 
            if (!(value is TElement))
            { 
                throw EntityUtil.IncompatibleArgument(); 
            }
 
            ((ICancelAddNew)this).EndNew(_addNewIndex);

            int index = ((IList)this).IndexOf(value);
 
            // Add the item if it doesn't already exist in the binding list.
            if (index == -1) 
            { 
                index = _viewData.Add((TElement)value, false);
 
                // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself.
                if (!_viewData.FiresEventOnAdd)
                {
                    _listener.RegisterEntityEvents(value); 
                    OnListChanged(ListChangedType.ItemAdded, index /*newIndex*/, -1/* oldIndex*/);
                } 
            } 

            return index; 
        }

        void IList.Clear()
        { 
            EnsureWritableList();
 
            ((ICancelAddNew)this).EndNew(_addNewIndex); 

            // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself. 
            if (_viewData.FiresEventOnClear)
            {
                _viewData.Clear();
            } 
            else
            { 
                try 
                {
                    // Suspend list changed events during the clear, since the IObjectViewData declared that it wouldn't fire an event. 
                    // It's possible the IObjectViewData could implement Clear by repeatedly calling Remove,
                    // and we don't want these events to percolate during the Clear operation.
                    _suspendEvent = true;
                    _viewData.Clear(); 
                }
                finally 
                { 
                    _suspendEvent = false;
                } 

                OnListChanged(ListChangedType.Reset, -1 /*newIndex*/, -1/* oldIndex*/); // Indexes not used for reset event.
            }
        } 

        bool IList.Contains(object value) 
        { 
            bool itemExists;
 
            if (value is TElement)
            {
                itemExists = _viewData.List.Contains((TElement)value);
            } 
            else
            { 
                itemExists = false; 
            }
 
            return itemExists;
        }

        int IList.IndexOf(object value) 
        {
            int index; 
 
            if (value is TElement)
            { 
                index = _viewData.List.IndexOf((TElement)value);
            }
            else
            { 
                index = -1;
            } 
 
            return index;
        } 

        void IList.Insert(int index, object value)
        {
            throw EntityUtil.IndexBasedInsertIsNotSupported(); 
        }
 
        void IList.Remove(object value) 
        {
            EnsureWritableList(); 

            EntityUtil.CheckArgumentNull(value, "value");

            if (!(value is TElement)) 
            {
                throw EntityUtil.IncompatibleArgument(); 
            } 

            Debug.Assert(((IList)this).Contains(value), "Value does not exist in view."); 

            ((ICancelAddNew)this).EndNew(_addNewIndex);

            TElement item = (TElement)value; 

            int index = _viewData.List.IndexOf(item); 
            bool removed = _viewData.Remove(item, false); 

            // Only fire a change event if the IObjectView data doesn't implicitly fire an event itself. 
            if (removed && !_viewData.FiresEventOnRemove)
            {
                _listener.UnregisterEntityEvents(item);
                OnListChanged(ListChangedType.ItemDeleted, index /* newIndex */, -1 /* oldIndex */); 
            }
        } 
 
        void IList.RemoveAt(int index)
        { 
            ((IList)this).Remove(((IList)this)[index]);
        }

        #endregion 

        #region  ICollection implementation 
 
        public int Count
        { 
            get { return _viewData.List.Count; }
        }

        public void CopyTo(Array array, int index) 
        {
            ((IList)_viewData.List).CopyTo(array, index); 
        } 

        object ICollection.SyncRoot 
        {
            get { return this; }
        }
 
        bool ICollection.IsSynchronized
        { 
            get { return false; } 
        }
 
        public IEnumerator GetEnumerator()
        {
            return _viewData.List.GetEnumerator();
        } 

        #endregion 
 
        private void OnListChanged(ListChangedType listchangedType, int newIndex, int oldIndex)
        { 
            ListChangedEventArgs changeArgs = new ListChangedEventArgs(listchangedType, newIndex, oldIndex);
            OnListChanged(changeArgs);
        }
 
        private void OnListChanged(ListChangedEventArgs changeArgs)
        { 
            // Only fire the event if someone listens to it and it is not suspended. 
            if (onListChanged != null && !_suspendEvent)
            { 
                onListChanged(this, changeArgs);
            }
        }
 
        void IObjectView.EntityPropertyChanged(object sender, PropertyChangedEventArgs e)
        { 
            Debug.Assert(sender is IEntityWithChangeTracker, "Should only receive events from IEntityWithChangeTracker objects."); 
            Debug.Assert(sender is TElement, "Entity should be of type TElement");
 
            int index = ((IList)this).IndexOf((TElement)sender);
            OnListChanged(ListChangedType.ItemChanged, index /*newIndex*/, index/*oldIndex*/);
        }
 
        /// 
        /// Handle a change in the underlying collection bound by this ObjectView. 
        ///  
        /// The source of the event.
        ///  
        /// Event arguments that specify the type of modification and the associated item.
        /// 
        void IObjectView.CollectionChanged(object sender, CollectionChangeEventArgs e)
        { 
            // If there is a pending edit of a new item in the bound list (indicated by _addNewIndex >= 0)
            // and the collection membership changed due to an operation external to this ObjectView, 
            // it is possible that the _addNewIndex position will need to be adjusted. 
            //
            // If the modification was made through this ObjectView, the pending edit would have been implicitly committed, 
            // and there would be no need to examine it here.
            TElement addNew = default(TElement);

            if (_addNewIndex >= 0) 
            {
                addNew = this[_addNewIndex]; 
            } 

            ListChangedEventArgs changeArgs = _viewData.OnCollectionChanged(sender, e, _listener); 

            if (_addNewIndex >= 0)
            {
                if (_addNewIndex >= this.Count) 
                {
                    _addNewIndex = ((IList)this).IndexOf(addNew); 
                } 
                else if (!this[_addNewIndex].Equals(addNew))
                { 
                    _addNewIndex = ((IList)this).IndexOf(addNew);
                }
            }
 
            if (changeArgs != null)
            { 
                OnListChanged(changeArgs); 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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