Example #1
0
        /// <summary>
        /// Remove an item from the direct children of a group.
        /// </summary>
        /// <param name="group">Group to remove item from</param>
        /// <param name="item">Item to remove</param>
        /// <returns>True if item could not be removed</returns>
        private bool RemoveFromGroupDirectly(CollectionViewGroupInternal group, object item)
        {
            int leafIndex = group.Remove(item, true);

            if (leafIndex >= 0)
            {
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, leafIndex));
                return(false);
            }
            else
            {
                return(true);
            }
        }
Example #2
0
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        /// <summary>
        /// Removes an empty group from the PagedCollectionView grouping
        /// </summary>
        /// <param name="group">Empty subgroup to remove</param>
        private static void RemoveEmptyGroup(CollectionViewGroupInternal group)
        {
            CollectionViewGroupInternal parent = group.Parent;

            if (parent != null)
            {
                GroupDescription groupBy = parent.GroupBy;
                int index = parent.ProtectedItems.IndexOf(group);

                // remove the subgroup unless it is one of the explicit groups
                if (index >= groupBy.GroupNames.Count)
                {
                    parent.Remove(group, false);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Finds the index of the specified item
        /// </summary>
        /// <param name="item">Item we are looking for</param>
        /// <param name="seed">Seed of the item we are looking for</param>
        /// <param name="comparer">Comparer used to find the item</param>
        /// <param name="low">Low range of item index</param>
        /// <param name="high">High range of item index</param>
        /// <returns>Index of the specified item</returns>
        protected virtual int FindIndex(object item, object seed, IComparer comparer, int low, int high)
        {
            int index;

            if (comparer != null)
            {
                ListComparer listComparer = comparer as ListComparer;
                if (listComparer != null)
                {
                    // reset the IListComparer before each search. This cannot be done
                    // any less frequently (e.g. in Root.AddToSubgroups), due to the
                    // possibility that the item may appear in more than one subgroup.
                    listComparer.Reset();
                }

                CollectionViewGroupComparer groupComparer = comparer as CollectionViewGroupComparer;
                if (groupComparer != null)
                {
                    // reset the CollectionViewGroupComparer before each search. This cannot be done
                    // any less frequently (e.g. in Root.AddToSubgroups), due to the
                    // possibility that the item may appear in more than one subgroup.
                    groupComparer.Reset();
                }

                for (index = low; index < high; ++index)
                {
                    CollectionViewGroupInternal subgroup = this.ProtectedItems[index] as CollectionViewGroupInternal;
                    object seed1 = (subgroup != null) ? subgroup.SeedItem : this.ProtectedItems[index];
                    if (seed1 == DependencyProperty.UnsetValue)
                    {
                        continue;
                    }

                    if (comparer.Compare(seed, seed1) < 0)
                    {
                        break;
                    }
                }
            }
            else
            {
                index = high;
            }

            return(index);
        }
Example #4
0
 /// <summary>
 /// 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.
 /// </summary>
 /// <param name="group">Group to remove item from</param>
 /// <param name="item">Item to remove</param>
 private void RemoveItemFromSubgroupsByExhaustiveSearch(CollectionViewGroupInternal group, object item)
 {
     // try to remove the item from the direct children
     // this function only returns true if it failed to remove from group directly
     // in which case we will step through and search exhaustively
     if (this.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)
             {
                 this.RemoveItemFromSubgroupsByExhaustiveSearch(subgroup, item);
             }
         }
     }
 }
Example #5
0
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        /// <summary>
        /// Add an item to the subgroup with the given name
        /// </summary>
        /// <param name="item">Item to add</param>
        /// <param name="group">Group to add item to</param>
        /// <param name="level">The level of grouping.</param>
        /// <param name="name">Name of subgroup to add to</param>
        /// <param name="loading">Whether we are currently loading</param>
        private void AddToSubgroup(object item, CollectionViewGroupInternal group, int level, object name, bool loading)
        {
            CollectionViewGroupInternal subgroup;
            int index = (this._isDataInGroupOrder) ? group.LastIndex : 0;

            // find the desired subgroup
            for (int n = group.Items.Count; index < n; ++index)
            {
                subgroup = group.Items[index] as CollectionViewGroupInternal;
                if (subgroup == null)
                {
                    continue;           // skip children that are not groups
                }

                if (group.GroupBy.NamesMatch(subgroup.Name, name))
                {
                    group.LastIndex = index;
                    this.AddToSubgroups(item, subgroup, level + 1, loading);
                    return;
                }
            }

            // the item didn't match any subgroups.  Create a new subgroup and add the item.
            subgroup = new CollectionViewGroupInternal(name, group);
            this.InitializeGroup(subgroup, level + 1, item);


            if (loading)
            {
                group.Add(subgroup);
                group.LastIndex = index;
            }
            else
            {
                // using insert will find the correct sort index to
                // place the subgroup, and will default to the last
                // position if no ActiveComparer is specified
                group.Insert(subgroup, item, this.ActiveComparer);
            }

            this.AddToSubgroups(item, subgroup, level + 1, loading);
        }
Example #6
0
            /// <summary>
            /// MoveNext implementation for IEnumerator
            /// </summary>
            /// <returns>Returns whether the MoveNext operation was successful</returns>
            bool IEnumerator.MoveNext()
            {
                Debug.Assert(this._group != null, "_group should have been initialized in constructor");

                // check for invalidated enumerator
                if (this._group._version != this._version)
                {
                    throw new InvalidOperationException();
                }

                // move forward to the next leaf
                while (this._subEnum == null || !this._subEnum.MoveNext())
                {
                    // done with the current top-level item.  Move to the next one.
                    ++this._index;
                    if (this._index >= this._group.Items.Count)
                    {
                        return(false);
                    }

                    CollectionViewGroupInternal subgroup = this._group.Items[this._index] as CollectionViewGroupInternal;
                    if (subgroup == null)
                    {
                        // current item is a leaf - it's the new Current
                        this._current = this._group.Items[this._index];
                        this._subEnum = null;
                        return(true);
                    }
                    else
                    {
                        // current item is a subgroup - get its enumerator
                        this._subEnum = subgroup.GetLeafEnumerator();
                    }
                }

                // the loop terminates only when we have a subgroup enumerator
                // positioned at the new Current item
                this._current = this._subEnum.Current;
                return(true);
            }
Example #7
0
        /// <summary>
        /// Initialize the given group
        /// </summary>
        /// <param name="group">Group to initialize</param>
        /// <param name="level">The level of grouping</param>
        /// <param name="seedItem">The seed item to compare with to see where to insert</param>
        private void InitializeGroup(CollectionViewGroupInternal group, int level, object seedItem)
        {
            // set the group description for dividing the group into subgroups
            GroupDescription groupDescription = this.GetGroupDescription(group, level);

            group.GroupBy = groupDescription;

            // create subgroups for each of the explicit names
            ObservableCollection <object> explicitNames =
                (groupDescription != null) ? groupDescription.GroupNames : null;

            if (explicitNames != null)
            {
                for (int k = 0, n = explicitNames.Count; k < n; ++k)
                {
                    CollectionViewGroupInternal subgroup = new CollectionViewGroupInternal(explicitNames[k], group);
                    this.InitializeGroup(subgroup, level + 1, seedItem);
                    group.Add(subgroup);
                }
            }

            group.LastIndex = 0;
        }
Example #8
0
        /// <summary>
        /// Returns the index of the given item within the list of leaves governed
        /// by this group
        /// </summary>
        /// <param name="item">Item we are looking for</param>
        /// <returns>Number of items under that leaf</returns>
        internal int LeafIndexOf(object item)
        {
            int leaves = 0;         // number of leaves we've passed over so far

            for (int k = 0, n = Items.Count; k < n; ++k)
            {
                CollectionViewGroupInternal subgroup = Items[k] as CollectionViewGroupInternal;
                if (subgroup != null)
                {
                    int subgroupIndex = subgroup.LeafIndexOf(item);
                    if (subgroupIndex < 0)
                    {
                        leaves += subgroup.ItemCount;       // item not in this subgroup
                    }
                    else
                    {
                        return(leaves + subgroupIndex);    // item is in this subgroup
                    }
                }
                else
                {
                    // current item is a leaf - compare it directly
                    if (object.Equals(item, Items[k]))
                    {
                        return(leaves);
                    }
                    else
                    {
                        leaves += 1;
                    }
                }
            }

            // item not found
            return(-1);
        }
        /// <summary>
        /// Remove an item from the subgroup with the given name.
        /// </summary>
        /// <param name="item">Item to remove</param>
        /// <param name="group">Group to remove item from</param>
        /// <param name="level">The level of grouping</param>
        /// <param name="name">Name of item to remove</param>
        /// <returns>Return true if the item was not in one of the subgroups it was supposed to be.</returns>
        private bool RemoveFromSubgroup(object item, CollectionViewGroupInternal group, int level, object name)
        {
            bool itemIsMissing = false;
            CollectionViewGroupInternal subgroup;

            // find the desired subgroup
            for (int index = 0, n = group.Items.Count; index < n; ++index)
            {
                subgroup = group.Items[index] as CollectionViewGroupInternal;
                if (subgroup == null)
                {
                    continue;           // skip children that are not groups
                }

                if (group.GroupBy.NamesMatch(subgroup.Name, name))
                {
                    if (this.RemoveFromSubgroups(item, subgroup, level + 1))
                    {
                        itemIsMissing = true;
                    }

                    return itemIsMissing;
                }
            }

            // the item didn't match any subgroups.  It should have.
            return true;
        }
Example #10
0
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of the CollectionViewGroupInternal class.
        /// </summary>
        /// <param name="name">Name of the CollectionViewGroupInternal</param>
        /// <param name="parent">Parent node of the CollectionViewGroup</param>
        internal CollectionViewGroupInternal(object name, CollectionViewGroupInternal parent)
            : base(name)
        {
            this._parentGroup = parent;
        }
            private int _version;   // parent group's version at ctor

            /// <summary>
            /// Initializes a new instance of the LeafEnumerator class.
            /// </summary>
            /// <param name="group">CollectionViewGroupInternal that uses the enumerator</param>
            public LeafEnumerator(CollectionViewGroupInternal group)
            {
                this._group = group;
                this.DoReset();  // don't call virtual Reset in ctor
            }
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        /// <summary>
        /// Removes an empty group from the PagedCollectionView grouping
        /// </summary>
        /// <param name="group">Empty subgroup to remove</param>
        private static void RemoveEmptyGroup(CollectionViewGroupInternal group)
        {
            CollectionViewGroupInternal parent = group.Parent;

            if (parent != null)
            {
                GroupDescription groupBy = parent.GroupBy;
                int index = parent.ProtectedItems.IndexOf(group);

                // remove the subgroup unless it is one of the explicit groups
                if (index >= groupBy.GroupNames.Count)
                {
                    parent.Remove(group, false);
                }
            }
        }
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of the CollectionViewGroupInternal class.
        /// </summary>
        /// <param name="name">Name of the CollectionViewGroupInternal</param>
        /// <param name="parent">Parent node of the CollectionViewGroup</param>
        internal CollectionViewGroupInternal(object name, CollectionViewGroupInternal parent)
            : base(name)
        {
            this._parentGroup = parent;
        }
 /// <summary>
 /// 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.
 /// </summary>
 /// <param name="group">Group to remove item from</param>
 /// <param name="item">Item to remove</param>
 private void RemoveItemFromSubgroupsByExhaustiveSearch(CollectionViewGroupInternal group, object item)
 {
     // try to remove the item from the direct children 
     // this function only returns true if it failed to remove from group directly
     // in which case we will step through and search exhaustively
     if (this.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)
             {
                 this.RemoveItemFromSubgroupsByExhaustiveSearch(subgroup, item);
             }
         }
     }
 }
        /// <summary>
        /// Remove an item from the desired subgroup(s) of the given group.
        /// </summary>
        /// <param name="item">Item to remove</param>
        /// <param name="group">Group to remove item from</param>
        /// <param name="level">The level of grouping</param>
        /// <returns>Return true if the item was not in one of the subgroups it was supposed to be.</returns>
        private bool RemoveFromSubgroups(object item, CollectionViewGroupInternal group, int level)
        {
            bool itemIsMissing = false;
            object name = this.GetGroupName(item, group.GroupBy, level);
            ICollection nameList;

            if (name == UseAsItemDirectly)
            {
                // the item belongs to the group itself (not to any subgroups)
                itemIsMissing = this.RemoveFromGroupDirectly(group, item);
            }
            else if ((nameList = name as ICollection) == null)
            {
                // the item belongs to one subgroup
                if (this.RemoveFromSubgroup(item, group, level, name))
                {
                    itemIsMissing = true;
                }
            }
            else
            {
                // the item belongs to multiple subgroups
                foreach (object o in nameList)
                {
                    if (this.RemoveFromSubgroup(item, group, level, o))
                    {
                        itemIsMissing = true;
                    }
                }
            }

            return itemIsMissing;
        }
 /// <summary>
 /// Remove an item from the direct children of a group.
 /// </summary>
 /// <param name="group">Group to remove item from</param>
 /// <param name="item">Item to remove</param>
 /// <returns>True if item could not be removed</returns>
 private bool RemoveFromGroupDirectly(CollectionViewGroupInternal group, object item)
 {
     int leafIndex = group.Remove(item, true);
     if (leafIndex >= 0)
     {
         this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, leafIndex));
         return false;
     }
     else
     {
         return true;
     }
 }
        /// <summary>
        /// Initialize the given group
        /// </summary>
        /// <param name="group">Group to initialize</param>
        /// <param name="level">The level of grouping</param>
        /// <param name="seedItem">The seed item to compare with to see where to insert</param>
        private void InitializeGroup(CollectionViewGroupInternal group, int level, object seedItem)
        {
            // set the group description for dividing the group into subgroups
            GroupDescription groupDescription = this.GetGroupDescription(group, level);
            group.GroupBy = groupDescription;

            // create subgroups for each of the explicit names
            ObservableCollection<object> explicitNames =
                (groupDescription != null) ? groupDescription.GroupNames : null;
            if (explicitNames != null)
            {
                for (int k = 0, n = explicitNames.Count; k < n; ++k)
                {
                    CollectionViewGroupInternal subgroup = new CollectionViewGroupInternal(explicitNames[k], group);
                    this.InitializeGroup(subgroup, level + 1, seedItem);
                    group.Add(subgroup);
                }
            }

            group.LastIndex = 0;
        }
        /// <summary>
        /// Add an item to the desired subgroup(s) of the given group
        /// </summary>
        /// <param name="item">Item to add</param>
        /// <param name="group">Group to add item to</param>
        /// <param name="level">The level of grouping</param>
        /// <param name="loading">Whether we are currently loading</param>
        private void AddToSubgroups(object item, CollectionViewGroupInternal group, int level, bool loading)
        {
            object name = this.GetGroupName(item, group.GroupBy, level);
            ICollection nameList;

            if (name == UseAsItemDirectly)
            {
                // the item belongs to the group itself (not to any subgroups)
                if (loading)
                {
                    group.Add(item);
                }
                else
                {
                    int localIndex = group.Insert(item, item, this.ActiveComparer);
                    int index = group.LeafIndexFromItem(item, localIndex);
                    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
                }
            }
            else if ((nameList = name as ICollection) == null)
            {
                // the item belongs to one subgroup
                this.AddToSubgroup(item, group, level, name, loading);
            }
            else
            {
                // the item belongs to multiple subgroups
                foreach (object o in nameList)
                {
                    this.AddToSubgroup(item, group, level, o, loading);
                }
            }
        }
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        /// <summary>
        /// Add an item to the subgroup with the given name
        /// </summary>
        /// <param name="item">Item to add</param>
        /// <param name="group">Group to add item to</param>
        /// <param name="level">The level of grouping.</param>
        /// <param name="name">Name of subgroup to add to</param>
        /// <param name="loading">Whether we are currently loading</param>
        private void AddToSubgroup(object item, CollectionViewGroupInternal group, int level, object name, bool loading)
        {
            CollectionViewGroupInternal subgroup;
            int index = (this._isDataInGroupOrder) ? group.LastIndex : 0;

            // find the desired subgroup
            for (int n = group.Items.Count; index < n; ++index)
            {
                subgroup = group.Items[index] as CollectionViewGroupInternal;
                if (subgroup == null)
                {
                    continue;           // skip children that are not groups
                }

                if (group.GroupBy.NamesMatch(subgroup.Name, name))
                {
                    group.LastIndex = index;
                    this.AddToSubgroups(item, subgroup, level + 1, loading);
                    return;
                }
            }

            // the item didn't match any subgroups.  Create a new subgroup and add the item.
            subgroup = new CollectionViewGroupInternal(name, group);
            this.InitializeGroup(subgroup, level + 1, item);


            if (loading)
            {
                group.Add(subgroup);
                group.LastIndex = index;
            }
            else
            {
                // using insert will find the correct sort index to
                // place the subgroup, and will default to the last
                // position if no ActiveComparer is specified
                group.Insert(subgroup, item, this.ActiveComparer);
            }

            this.AddToSubgroups(item, subgroup, level + 1, loading);
        }
Example #20
0
            private int _version;                                // parent group's version at ctor

            /// <summary>
            /// Initializes a new instance of the LeafEnumerator class.
            /// </summary>
            /// <param name="group">CollectionViewGroupInternal that uses the enumerator</param>
            public LeafEnumerator(CollectionViewGroupInternal group)
            {
                this._group = group;
                this.DoReset();  // don't call virtual Reset in ctor
            }