CollectionViewGroupRoot.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Data / CollectionViewGroupRoot.cs / 1305600 / CollectionViewGroupRoot.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Root of CollectionViewGroup structure, as created by a CollectionView according to a GroupDescription. 
//                  CollectionView classes use this class to manage all Grouping functionality.
// 
// See spec at http://avalon/connecteddata/Specs/Grouping.mht
//
//---------------------------------------------------------------------------
 
using System;
using System.Collections;       // IComparer 
using System.Collections.ObjectModel;   // ObservableCollection 
using System.Collections.Specialized;   // INotifyCollectionChanged
using System.ComponentModel;    // PropertyChangedEventArgs, GroupDescription 
using System.Diagnostics;       // Debug.Assert
using System.Globalization;
using System.Windows.Data;      // CollectionViewGroup
 
namespace MS.Internal.Data
{ 
 
    // CollectionView classes use this class as the manager of all Grouping functionality
    internal class CollectionViewGroupRoot : CollectionViewGroupInternal, INotifyCollectionChanged 
    {
        internal CollectionViewGroupRoot(CollectionView view) : base("Root", null)
        {
            _view = view; 
        }
 
#region INotifyCollectionChanged 
        /// 
        /// Raise this event when the (grouped) view changes 
        /// 
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        ///  
        ///     Notify listeners that this View has changed
        ///  
        ///  
        ///     CollectionViews (and sub-classes) should take their filter/sort/grouping
        ///     into account before calling this method to forward CollectionChanged events. 
        /// 
        /// 
        ///     The NotifyCollectionChangedEventArgs to be passed to the EventHandler
        ///  
        public void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
        { 
            if (args == null) 
                throw new ArgumentNullException("args");
 
            if (CollectionChanged != null)
                CollectionChanged(this, args);
        }
#endregion INotifyCollectionChanged 

        ///  
        /// The description of grouping, indexed by level. 
        /// 
        public virtual ObservableCollection GroupDescriptions 
        {
            get { return _groupBy; }
        }
 
        /// 
        /// A delegate to select the group description as a function of the 
        /// parent group and its level. 
        /// 
        public virtual GroupDescriptionSelectorCallback GroupBySelector 
        {
            get { return _groupBySelector; }
            set { _groupBySelector = value; }
        } 

        // a group description has changed somewhere in the tree - notify host 
        protected override void OnGroupByChanged() 
        {
            if (GroupDescriptionChanged != null) 
                GroupDescriptionChanged(this, EventArgs.Empty);
        }

#region Internal Events and Properties 

        internal event EventHandler GroupDescriptionChanged; 
 
        internal IComparer ActiveComparer
        { 
            get { return _comparer; }
            set { _comparer = value; }
        }
 
        /// 
        /// Culture to use during sorting. 
        ///  
        internal CultureInfo Culture
        { 
            get { return _view.Culture; }
        }

        internal bool IsDataInGroupOrder 
        {
            get { return _isDataInGroupOrder; } 
            set { _isDataInGroupOrder = value; } 
        }
 
#endregion Internal Events and Properties

#region Internal Methods
 
        internal void Initialize()
        { 
            if (_topLevelGroupDescription == null) 
            {
                _topLevelGroupDescription = new TopLevelGroupDescription(); 
            }
            InitializeGroup(this, _topLevelGroupDescription, 0);
        }
 
        internal void AddToSubgroups(object item, bool loading)
        { 
            AddToSubgroups(item, this, 0, loading); 
        }
 
        internal bool RemoveFromSubgroups(object item)
        {
            return RemoveFromSubgroups(item, this, 0);
        } 

        internal void RemoveItemFromSubgroupsByExhaustiveSearch(object item) 
        { 
            RemoveItemFromSubgroupsByExhaustiveSearch(this, item);
        } 

        internal void InsertSpecialItem(int index, object item, bool loading)
        {
            ChangeCounts(item, +1); 
            ProtectedItems.Insert(index, item);
 
            if (!loading) 
            {
                int globalIndex = this.LeafIndexFromItem(item, index); 
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, globalIndex));
            }
        }
 
        internal void RemoveSpecialItem(int index, object item, bool loading)
        { 
            Debug.Assert(Object.Equals(item, ProtectedItems[index]), "RemoveSpecialItem finds inconsistent data"); 
            int globalIndex = -1;
 
            if (!loading)
            {
                globalIndex = this.LeafIndexFromItem(item, index);
            } 

            ChangeCounts(item, -1); 
            ProtectedItems.RemoveAt(index); 

            if (!loading) 
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, globalIndex));
            }
        } 

        protected override int FindIndex(object item, object seed, IComparer comparer, int low, int high) 
        { 
            // root group needs to adjust the bounds of the search to exclude the
            // placeholder and new item (if any) 
            IEditableCollectionView iecv = _view as IEditableCollectionView;
            if (iecv != null)
            {
                if (iecv.NewItemPlaceholderPosition == NewItemPlaceholderPosition.AtBeginning) 
                {
                    ++low; 
                    if (iecv.IsAddingNew) 
                    {
                        ++low; 
                    }
                }
                else
                { 
                    if (iecv.IsAddingNew)
                    { 
                        --high; 
                    }
                    if (iecv.NewItemPlaceholderPosition == NewItemPlaceholderPosition.AtEnd) 
                    {
                        --high;
                    }
                } 
            }
 
            return base.FindIndex(item, seed, comparer, low, high); 
        }
 

#endregion Internal Methods

#region private methods 

        // Initialize the given group 
        void InitializeGroup(CollectionViewGroupInternal group, GroupDescription parentDescription, int level) 
        {
            // set the group description for dividing the group into subgroups 
            GroupDescription groupDescription = GetGroupDescription(group, parentDescription, level);
            group.GroupBy = groupDescription;

            // create subgroups for each of the explicit names 
            ObservableCollection explicitNames =
                        (groupDescription != null) ? groupDescription.GroupNames : null; 
            if (explicitNames != null) 
            {
                for (int k=0, n=explicitNames.Count;  k= 0)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, leafIndex)); 
                return false;
            } 
            else 
            {
                return true; 
            }
        }

        // the item did not appear in one or more of the subgroups it 
        // was supposed to.  This can happen if the item's properties
        // change so that the group names we used to insert it are 
        // different from the names used to remove it.  If this happens, 
        // remove the item the hard way.
        void RemoveItemFromSubgroupsByExhaustiveSearch(CollectionViewGroupInternal group, object item) 
        {
            // try to remove the item from the direct children
            if (RemoveFromGroupDirectly(group, item))
            { 
                // if that didn't work, recurse into each subgroup
                // (loop runs backwards in case an entire group is deleted) 
                for (int k=group.Items.Count-1;  k >= 0;  --k) 
                {
                    CollectionViewGroupInternal subgroup = group.Items[k] as CollectionViewGroupInternal; 
                    if (subgroup != null)
                    {
                        RemoveItemFromSubgroupsByExhaustiveSearch(subgroup, item);
                    } 
                }
            } 
            else 
            {
                // if the item was removed directly, we don't have to look at subgroups. 
                // An item cannot appear both as a direct child and as a deeper descendant.
            }
        }
 

        // get the group name(s) for the given item 
        object GetGroupName(object item, GroupDescription groupDescription, int level) 
        {
            if (groupDescription != null) 
            {
                return groupDescription.GroupNameFromItem(item, level, Culture);
            }
            else 
            {
                return UseAsItemDirectly; 
            } 
        }
#endregion private methods 

#region private fields
        CollectionView _view;
        IComparer _comparer; 
        bool _isDataInGroupOrder = false;
 
        ObservableCollection _groupBy = new ObservableCollection(); 
        GroupDescriptionSelectorCallback _groupBySelector;
        static GroupDescription _topLevelGroupDescription; 
        static readonly object UseAsItemDirectly = new NamedObject("UseAsItemDirectly");
#endregion private fields

#region private types 
        private class TopLevelGroupDescription : GroupDescription
        { 
            public TopLevelGroupDescription() 
            {
            } 

            // we have to implement this abstract method, but it should never be called
            public override object GroupNameFromItem(object item, int level, System.Globalization.CultureInfo culture)
            { 
                throw new NotSupportedException();
            } 
        } 
#endregion private types
    } 

}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Root of CollectionViewGroup structure, as created by a CollectionView according to a GroupDescription. 
//                  CollectionView classes use this class to manage all Grouping functionality.
// 
// See spec at http://avalon/connecteddata/Specs/Grouping.mht
//
//---------------------------------------------------------------------------
 
using System;
using System.Collections;       // IComparer 
using System.Collections.ObjectModel;   // ObservableCollection 
using System.Collections.Specialized;   // INotifyCollectionChanged
using System.ComponentModel;    // PropertyChangedEventArgs, GroupDescription 
using System.Diagnostics;       // Debug.Assert
using System.Globalization;
using System.Windows.Data;      // CollectionViewGroup
 
namespace MS.Internal.Data
{ 
 
    // CollectionView classes use this class as the manager of all Grouping functionality
    internal class CollectionViewGroupRoot : CollectionViewGroupInternal, INotifyCollectionChanged 
    {
        internal CollectionViewGroupRoot(CollectionView view) : base("Root", null)
        {
            _view = view; 
        }
 
#region INotifyCollectionChanged 
        /// 
        /// Raise this event when the (grouped) view changes 
        /// 
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        ///  
        ///     Notify listeners that this View has changed
        ///  
        ///  
        ///     CollectionViews (and sub-classes) should take their filter/sort/grouping
        ///     into account before calling this method to forward CollectionChanged events. 
        /// 
        /// 
        ///     The NotifyCollectionChangedEventArgs to be passed to the EventHandler
        ///  
        public void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
        { 
            if (args == null) 
                throw new ArgumentNullException("args");
 
            if (CollectionChanged != null)
                CollectionChanged(this, args);
        }
#endregion INotifyCollectionChanged 

        ///  
        /// The description of grouping, indexed by level. 
        /// 
        public virtual ObservableCollection GroupDescriptions 
        {
            get { return _groupBy; }
        }
 
        /// 
        /// A delegate to select the group description as a function of the 
        /// parent group and its level. 
        /// 
        public virtual GroupDescriptionSelectorCallback GroupBySelector 
        {
            get { return _groupBySelector; }
            set { _groupBySelector = value; }
        } 

        // a group description has changed somewhere in the tree - notify host 
        protected override void OnGroupByChanged() 
        {
            if (GroupDescriptionChanged != null) 
                GroupDescriptionChanged(this, EventArgs.Empty);
        }

#region Internal Events and Properties 

        internal event EventHandler GroupDescriptionChanged; 
 
        internal IComparer ActiveComparer
        { 
            get { return _comparer; }
            set { _comparer = value; }
        }
 
        /// 
        /// Culture to use during sorting. 
        ///  
        internal CultureInfo Culture
        { 
            get { return _view.Culture; }
        }

        internal bool IsDataInGroupOrder 
        {
            get { return _isDataInGroupOrder; } 
            set { _isDataInGroupOrder = value; } 
        }
 
#endregion Internal Events and Properties

#region Internal Methods
 
        internal void Initialize()
        { 
            if (_topLevelGroupDescription == null) 
            {
                _topLevelGroupDescription = new TopLevelGroupDescription(); 
            }
            InitializeGroup(this, _topLevelGroupDescription, 0);
        }
 
        internal void AddToSubgroups(object item, bool loading)
        { 
            AddToSubgroups(item, this, 0, loading); 
        }
 
        internal bool RemoveFromSubgroups(object item)
        {
            return RemoveFromSubgroups(item, this, 0);
        } 

        internal void RemoveItemFromSubgroupsByExhaustiveSearch(object item) 
        { 
            RemoveItemFromSubgroupsByExhaustiveSearch(this, item);
        } 

        internal void InsertSpecialItem(int index, object item, bool loading)
        {
            ChangeCounts(item, +1); 
            ProtectedItems.Insert(index, item);
 
            if (!loading) 
            {
                int globalIndex = this.LeafIndexFromItem(item, index); 
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, globalIndex));
            }
        }
 
        internal void RemoveSpecialItem(int index, object item, bool loading)
        { 
            Debug.Assert(Object.Equals(item, ProtectedItems[index]), "RemoveSpecialItem finds inconsistent data"); 
            int globalIndex = -1;
 
            if (!loading)
            {
                globalIndex = this.LeafIndexFromItem(item, index);
            } 

            ChangeCounts(item, -1); 
            ProtectedItems.RemoveAt(index); 

            if (!loading) 
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, globalIndex));
            }
        } 

        protected override int FindIndex(object item, object seed, IComparer comparer, int low, int high) 
        { 
            // root group needs to adjust the bounds of the search to exclude the
            // placeholder and new item (if any) 
            IEditableCollectionView iecv = _view as IEditableCollectionView;
            if (iecv != null)
            {
                if (iecv.NewItemPlaceholderPosition == NewItemPlaceholderPosition.AtBeginning) 
                {
                    ++low; 
                    if (iecv.IsAddingNew) 
                    {
                        ++low; 
                    }
                }
                else
                { 
                    if (iecv.IsAddingNew)
                    { 
                        --high; 
                    }
                    if (iecv.NewItemPlaceholderPosition == NewItemPlaceholderPosition.AtEnd) 
                    {
                        --high;
                    }
                } 
            }
 
            return base.FindIndex(item, seed, comparer, low, high); 
        }
 

#endregion Internal Methods

#region private methods 

        // Initialize the given group 
        void InitializeGroup(CollectionViewGroupInternal group, GroupDescription parentDescription, int level) 
        {
            // set the group description for dividing the group into subgroups 
            GroupDescription groupDescription = GetGroupDescription(group, parentDescription, level);
            group.GroupBy = groupDescription;

            // create subgroups for each of the explicit names 
            ObservableCollection explicitNames =
                        (groupDescription != null) ? groupDescription.GroupNames : null; 
            if (explicitNames != null) 
            {
                for (int k=0, n=explicitNames.Count;  k= 0)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, leafIndex)); 
                return false;
            } 
            else 
            {
                return true; 
            }
        }

        // the item did not appear in one or more of the subgroups it 
        // was supposed to.  This can happen if the item's properties
        // change so that the group names we used to insert it are 
        // different from the names used to remove it.  If this happens, 
        // remove the item the hard way.
        void RemoveItemFromSubgroupsByExhaustiveSearch(CollectionViewGroupInternal group, object item) 
        {
            // try to remove the item from the direct children
            if (RemoveFromGroupDirectly(group, item))
            { 
                // if that didn't work, recurse into each subgroup
                // (loop runs backwards in case an entire group is deleted) 
                for (int k=group.Items.Count-1;  k >= 0;  --k) 
                {
                    CollectionViewGroupInternal subgroup = group.Items[k] as CollectionViewGroupInternal; 
                    if (subgroup != null)
                    {
                        RemoveItemFromSubgroupsByExhaustiveSearch(subgroup, item);
                    } 
                }
            } 
            else 
            {
                // if the item was removed directly, we don't have to look at subgroups. 
                // An item cannot appear both as a direct child and as a deeper descendant.
            }
        }
 

        // get the group name(s) for the given item 
        object GetGroupName(object item, GroupDescription groupDescription, int level) 
        {
            if (groupDescription != null) 
            {
                return groupDescription.GroupNameFromItem(item, level, Culture);
            }
            else 
            {
                return UseAsItemDirectly; 
            } 
        }
#endregion private methods 

#region private fields
        CollectionView _view;
        IComparer _comparer; 
        bool _isDataInGroupOrder = false;
 
        ObservableCollection _groupBy = new ObservableCollection(); 
        GroupDescriptionSelectorCallback _groupBySelector;
        static GroupDescription _topLevelGroupDescription; 
        static readonly object UseAsItemDirectly = new NamedObject("UseAsItemDirectly");
#endregion private fields

#region private types 
        private class TopLevelGroupDescription : GroupDescription
        { 
            public TopLevelGroupDescription() 
            {
            } 

            // we have to implement this abstract method, but it should never be called
            public override object GroupNameFromItem(object item, int level, System.Globalization.CultureInfo culture)
            { 
                throw new NotSupportedException();
            } 
        } 
#endregion private types
    } 

}


// 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