Exemple #1
0
        internal Group(
            GroupGeneratorNode node,
            CollectionViewGroup group,
            LateGroupLevelDescription groupLevelDescription,
            DataGridContext dataGridContext)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (group == null)
            {
                throw new ArgumentNullException("group");
            }

            if (groupLevelDescription == null)
            {
                throw new ArgumentNullException("groupLevelDescription");
            }

            if (dataGridContext == null)
            {
                throw new ArgumentNullException("dataGridContext");
            }

            m_collectionViewGroup = group;

            // Initialization is done through setters to register for events.
            this.DataGridContext       = dataGridContext;
            this.GeneratorNode         = node;
            this.GroupLevelDescription = groupLevelDescription;
        }
Exemple #2
0
        public void CleanGeneratorNodeTree(GeneratorNode node)
        {
            if (node.Parent != null)
            {
                node.Parent.AdjustItemCount(-node.ItemCount);

                GroupGeneratorNode parentGroupNode = node.Parent as GroupGeneratorNode;
                if ((parentGroupNode != null) && (parentGroupNode.Child == node))
                {
                    parentGroupNode.Child = null;
                }
            }

            GeneratorNode child;
            GeneratorNode next;

            do
            {
                GroupGeneratorNode groupNode = node as GroupGeneratorNode;

                next  = node.Next;
                child = (groupNode != null) ? groupNode.Child : null;

                this.CleanGeneratorNode(node);

                //this recursive function cleans up the tree of nodes
                if (child != null)
                {
                    this.CleanGeneratorNodeTree(child);
                }

                node = next;
            }while(node != null);
        }
Exemple #3
0
        private void UnregisterItemCountEvent(GroupGeneratorNode item)
        {
            if (item == null)
            {
                return;
            }

            item.TotalLeafCountChanged -= new EventHandler(this.OnItemCountChanged);
        }
Exemple #4
0
        private void UnregisterIsExpandedEvent(GroupGeneratorNode item)
        {
            if (item == null)
            {
                return;
            }

            item.IsExpandedChanged -= new EventHandler(this.OnIsExpandedChanged);
        }
        protected override int AdjustItemCountOverride(int delta)
        {
            base.AdjustItemCountOverride(delta);

            GroupGeneratorNode parentGroup = this.Parent as GroupGeneratorNode;

            if ((parentGroup != null) && (parentGroup.IsExpanded == false))
            {
                return(0);
            }

            return(delta);
        }
Exemple #6
0
        //Note: this function will not check for the presence of the group in the details for Items nodes.
        public bool FindGroup(CollectionViewGroup group)
        {
            if (group == null)
            {
                return(false);
            }

            GeneratorNode originalNode            = m_currentNode;
            int           originalIndex           = m_index;
            int           originalSourceDataIndex = m_sourceDataIndex;

            do
            {
                GroupGeneratorNode groupNode = m_currentNode as GroupGeneratorNode;
                if (groupNode != null)
                {
                    if (groupNode.CollectionViewGroup == group)
                    {
                        return(true);
                    }

                    if (!groupNode.CollectionViewGroup.IsBottomLevel)
                    {
                        if (!this.MoveToChild(false))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (!this.MoveToFollowing())
                        {
                            break;
                        }
                    }
                }
                else
                {
                    //There can be nothing under a non-GroupGeneratorNode, try to move Next node in the list.
                    if (!this.MoveToFollowing())
                    {
                        break;
                    }
                }
            } while(true);

            m_currentNode     = originalNode;
            m_index           = originalIndex;
            m_sourceDataIndex = originalSourceDataIndex;
            return(false);
        }
        private int IndexOfHelper(GroupGeneratorNode parentGroup, object template)
        {
            int retval = -1;

            if (parentGroup != null && parentGroup.IsExpanded == false)
            {
                retval = this.ComputeCollapsedIndexOf(template);
            }
            else
            {
                retval = base.IndexOf(template);
            }

            return(retval);
        }
        internal void BuildNamesTree()
        {
            int level = this.Level;

            m_namesTree = new object[level + 1];

            m_namesTree[level] = this.CollectionViewGroup.Name;

            GroupGeneratorNode parentNode = this.Parent as GroupGeneratorNode;

            for (int i = level - 1; i >= 0; i--)
            {
                m_namesTree[i] = parentNode.CollectionViewGroup.Name;
                parentNode     = parentNode.Parent as GroupGeneratorNode;
            }
        }
        internal ReadOnlyCollection <Group> GetImmediateUIGroups(int generatorCurrentGeneration)
        {
            if ((m_cachedGeneratorCurrentGeneration != generatorCurrentGeneration) ||
                (m_readOnlyImmediateUIGroups == null))
            {
                Debug.WriteLineIf(((m_cachedGeneratorCurrentGeneration != generatorCurrentGeneration) && (m_readOnlyImmediateUIGroups == null)),
                                  "Creating Groups collection since generator version differs AND ReadOnlyCollection is null.");

                Debug.WriteLineIf(((m_cachedGeneratorCurrentGeneration != generatorCurrentGeneration) && (m_readOnlyImmediateUIGroups != null)),
                                  "Creating Groups collection since generator version differs.");

                Debug.WriteLineIf(((m_cachedGeneratorCurrentGeneration == generatorCurrentGeneration) && (m_readOnlyImmediateUIGroups == null)),
                                  "Creating Groups collection even if generator version is the same, since ReadOnlyCollection is null.");

                m_cachedGeneratorCurrentGeneration = generatorCurrentGeneration;

                // Ensure collections.
                if (m_immediateUIGroups == null)
                {
                    Debug.Assert(m_readOnlyImmediateUIGroups == null);
                    m_immediateUIGroups         = new Collection <Group>();
                    m_readOnlyImmediateUIGroups = new ReadOnlyCollection <Group>(m_immediateUIGroups);
                }
                else
                {
                    Debug.Assert(m_readOnlyImmediateUIGroups != null);
                    m_immediateUIGroups.Clear();
                }

                // Recalculate.
                GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper(this, 0, 0); //index is not important

                while (nodeHelper.MoveToNext())
                {
                    GroupGeneratorNode groupGeneratorNode = nodeHelper.CurrentNode as GroupGeneratorNode;

                    if (groupGeneratorNode == null)
                    {
                        continue;
                    }

                    m_immediateUIGroups.Add(groupGeneratorNode.UIGroup);
                }
            }

            return(m_readOnlyImmediateUIGroups);
        }
Exemple #10
0
        public bool MoveToChild(bool skipItemLessGroupNodes)
        {
            GroupGeneratorNode groupNode = m_currentNode as GroupGeneratorNode;

            if ((groupNode == null) || (groupNode.Child == null))
            {
                return(false);
            }

            if ((skipItemLessGroupNodes) && (!(groupNode.ItemCount > 0)))
            {
                return(false);
            }

            m_currentNode = groupNode.Child;
            return(true);
        }
Exemple #11
0
        private void RegisterIsExpandedEvent(GroupGeneratorNode item, bool force)
        {
            if (item == null)
            {
                return;
            }

            lock (this.SyncRoot)
            {
                if (!force && (m_propertyChanged == null))
                {
                    return;
                }

                item.IsExpandedChanged += new EventHandler(this.OnIsExpandedChanged);
            }
        }
Exemple #12
0
        private void RegisterItemCountEvent(GroupGeneratorNode item, bool force)
        {
            if (item == null)
            {
                return;
            }

            lock (this.SyncRoot)
            {
                if (!force && (m_propertyChanged == null))
                {
                    return;
                }

                item.TotalLeafCountChanged += new EventHandler(this.OnItemCountChanged);
            }
        }
Exemple #13
0
        //-------------
        // Methods

        public bool MoveToNext()
        {
            if (m_currentNode.Next != null)
            {
                GroupGeneratorNode groupNode = m_currentNode as GroupGeneratorNode;

                if (groupNode != null)
                {
                    m_sourceDataIndex += groupNode.TotalLeafCount;
                }

                m_index      += m_currentNode.ItemCount;
                m_currentNode = m_currentNode.Next;
                return(true);
            }

            return(false);
        }
Exemple #14
0
        //internal use only
        public bool MoveToPrevious()
        {
            if (m_currentNode.Previous != null)
            {
                m_currentNode = m_currentNode.Previous;
                GroupGeneratorNode groupNode = m_currentNode as GroupGeneratorNode;

                if (groupNode != null)
                {
                    m_sourceDataIndex -= groupNode.TotalLeafCount;
                }

                m_index -= m_currentNode.ItemCount;
                return(true);
            }

            return(false);
        }
Exemple #15
0
        private readonly WeakReference m_dataGridControl; //null

        #endregion

        public GeneratorNode CreateGroupGeneratorNode(
            CollectionViewGroup collectionViewGroup,
            GeneratorNode parent,
            GeneratorNode previous,
            GeneratorNode next,
            GroupConfiguration groupConfig)
        {
            Debug.Assert(collectionViewGroup != null, "collectionViewGroup cannot be null for CreateGroupGeneratorNode()");

            GroupGeneratorNode node = new GroupGeneratorNode(collectionViewGroup, parent, groupConfig);

            if (previous != null)
            {
                previous.Next = node;
            }
            node.Previous = previous;

            if (next != null)
            {
                next.Previous = node;
            }
            node.Next = next;

            node.IsExpanded = groupConfig.InitiallyExpanded;

            if (!collectionViewGroup.IsBottomLevel)
            {
                this.RegisterNodeCollectionChanged(
                    ( INotifyCollectionChanged )collectionViewGroup.GetItems(),
                    new NotifyCollectionChangedEventHandler(node.OnCollectionChanged));

                node.CollectionChanged += m_groupsChangedHandler;
            }

            node.ExpansionStateChanged += m_expansionStateChangedHandler;
            node.IsExpandedChanging    += m_isExpandedChangingHandler;
            node.IsExpandedChanged     += m_isExpandedChangedHandler;

            node.AdjustItemCount(node.ItemCount);

            node.BuildNamesTree();

            return(node);
        }
Exemple #16
0
        public bool MoveBackward()
        {
            bool recurseGroup = true;
            GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper(m_currentNode, m_index, m_sourceDataIndex);

            do
            {
                GroupGeneratorNode groupNode = nodeHelper.CurrentNode as GroupGeneratorNode;

                if ((groupNode == null) && (nodeHelper.CurrentNode != m_currentNode) && (nodeHelper.CurrentNode.ItemCount != 0))
                {
                    m_currentNode     = nodeHelper.CurrentNode;
                    m_index           = nodeHelper.Index;
                    m_sourceDataIndex = nodeHelper.SourceDataIndex;
                    return(true);
                }

                if ((recurseGroup) && (nodeHelper.MoveToChild()))
                {
                    nodeHelper.MoveToEnd();
                    continue;
                }

                recurseGroup = true;

                if (nodeHelper.MoveToPrevious())
                {
                    continue;
                }


                if (nodeHelper.MoveToParent())
                {
                    recurseGroup = false;
                    continue;
                }

                break;
            }while(true);

            return(false);
        }
        public override object GetAt(int index)
        {
            object             retval      = null;
            GroupGeneratorNode parentGroup = this.Parent as GroupGeneratorNode;

            if ((parentGroup != null) && (parentGroup.IsExpanded == false))
            {
                retval = this.ComputeCollapsedGetAt(index);
            }
            else
            {
                retval = base.GetAt(index);
            }

            if (parentGroup != null)
            {
                retval = new GroupHeaderFooterItem(parentGroup.CollectionViewGroup, retval);
            }

            return(retval);
        }
        internal static HeadersFootersGeneratorNode GetSameLevelFirstHeaderNode(GroupGeneratorNode generatorNode)
        {
            HeadersFootersGeneratorNode headerGeneratorNode = null;

            GroupGeneratorNode parentGroupGeneratorNode = generatorNode.Parent as GroupGeneratorNode;

            if (parentGroupGeneratorNode == null)
            {
                GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper(generatorNode, 0, 0); //index is not important

                if (nodeHelper.MoveToFirst())
                {
                    headerGeneratorNode = nodeHelper.CurrentNode as HeadersFootersGeneratorNode;
                }
            }
            else
            {
                headerGeneratorNode = parentGroupGeneratorNode.Child as HeadersFootersGeneratorNode;
            }

            return(headerGeneratorNode);
        }
Exemple #19
0
        private static void ProcessHeadersNodeVisit(HeadersFootersGeneratorNode headersNode, DataGridContext sourceContext, int minIndex, int maxIndex, IDataGridContextVisitor visitor, ref bool stopVisit)
        {
            for (int i = minIndex; i <= maxIndex; i++)
            {
                object template = headersNode.GetAt(i);

                GroupGeneratorNode groupNode = headersNode.Parent as GroupGeneratorNode;
                if (groupNode != null)
                {
                    visitor.Visit(sourceContext, ( GroupHeaderFooterItem )template, ref stopVisit);
                }
                else
                {
                    visitor.Visit(sourceContext, ( DataTemplate )template, ref stopVisit);
                }

                if (stopVisit)
                {
                    break;
                }
            }
        }
        public override int IndexOf(object item)
        {
            int retval = -1;

            if (item != null)
            {
                GroupGeneratorNode parentGroup = this.Parent as GroupGeneratorNode;

                //if the node is the child of a GroupGeneratorNode (then its a GroupHeader or GroupFooter).
                if (parentGroup != null)
                {
                    //Debug.Assert( ( item.GetType() == typeof( GroupHeaderFooterItem ) ), "item must be a GroupHeaderFooterItem for HeadersFootersGeneratorNode whose parent is a GroupGeneratorNode" );

                    if (item.GetType() == typeof(GroupHeaderFooterItem))
                    {
                        //only process further is the ParentGroup match the requested group.
                        GroupHeaderFooterItem ghf = ( GroupHeaderFooterItem )item;
                        if (ghf.Group == parentGroup.CollectionViewGroup)
                        {
                            retval = this.IndexOfHelper(parentGroup, ghf.Template);
                        }
                    }
                    else
                    {
                        retval = this.IndexOfHelper(parentGroup, item);
                    }
                }
                else
                {
                    //if there is no parent group (or no parent at all), then process the item directly!
                    retval = this.IndexOfHelper(parentGroup, item);
                }
            }

            return(retval);
        }
Exemple #21
0
        public bool InsertBefore(GeneratorNode insert)
        {
            if (insert == null)
            {
                throw new DataGridInternalException("GeneratorNode is null");
            }

            int           insertionCount;
            int           chainLength;
            GeneratorNode insertLast = GeneratorNodeHelper.EvaluateChain(insert, out insertionCount, out chainLength);
            GeneratorNode previous   = m_currentNode.Previous;

            if (previous != null)
            {
                previous.Next = insert;
            }

            insert.Previous        = previous;
            m_currentNode.Previous = insertLast;
            insertLast.Next        = m_currentNode;

            GroupGeneratorNode parentGroup = insert.Parent as GroupGeneratorNode;

            if (parentGroup != null)
            {
                if (parentGroup.Child == m_currentNode)
                {
                    parentGroup.Child = insert;
                }
            }

            // Move the current to the first item inserted.
            // No need to change m_index, m_sourceDataIndex since they will still be with the correct value.
            m_currentNode = insert;
            return(true);
        }
Exemple #22
0
        public void CleanGeneratorNode(GeneratorNode node)
        {
            HeadersFootersGeneratorNode headersFootersNode = node as HeadersFootersGeneratorNode;

            if (headersFootersNode != null)
            {
                this.CleanHeadersFootersNotification(headersFootersNode);
            }
            else
            {
                ItemsGeneratorNode itemsNode = node as ItemsGeneratorNode;
                if (itemsNode != null)
                {
                    this.UnregisterNodeCollectionChanged(( INotifyCollectionChanged )itemsNode.Items);
                    itemsNode.CollectionChanged -= m_itemsChangedHandler;
                }
                else
                {
                    GroupGeneratorNode groupNode = node as GroupGeneratorNode;
                    if (groupNode != null)
                    {
                        IList <object> subItems = groupNode.CollectionViewGroup.GetItems();

                        this.UnregisterNodeCollectionChanged(( INotifyCollectionChanged )subItems);

                        groupNode.CollectionChanged  -= m_groupsChangedHandler;
                        groupNode.IsExpandedChanging -= m_isExpandedChangingHandler;
                        groupNode.IsExpandedChanged  -= m_isExpandedChangedHandler;
                    }
                }
            }

            node.ExpansionStateChanged -= m_expansionStateChangedHandler;

            node.CleanGeneratorNode();
        }
Exemple #23
0
        public void ProcessVisit(
            DataGridContext sourceContext,
            int minIndex,
            int maxIndex,
            IDataGridContextVisitor visitor,
            DataGridContextVisitorType visitorType,
            bool visitDetails,
            out bool visitWasStopped)
        {
            visitWasStopped = false;

            // This is used only for DataGridContextVisitorType.ItemsBlock
            int startSourceDataItemIndex = -1;
            int endSourceDataItemIndex   = -1;

            if (minIndex < 0)
            {
                DataGridException.ThrowSystemException("The minimum index must be greater than or equal to zero.",
                                                       typeof(ArgumentException), sourceContext.DataGridControl.Name, "minIndex");
            }

            if ((visitorType & DataGridContextVisitorType.DataGridContext) == DataGridContextVisitorType.DataGridContext)
            {
                visitor.Visit(sourceContext, ref visitWasStopped);

                if (visitWasStopped)
                {
                    return;
                }
            }

            //Take a shortcut, if the visit is made only for contexts, and there is no child contexts
            //return right away.
            bool containsDetails = false;

            foreach (DataGridContext childContext in sourceContext.GetChildContexts())
            {
                containsDetails = true;
                break;
            }

            bool processed = false;

            do
            {
                //resets the flag that indicates if the node was already processed
                processed = false;

                int itemCount = this.CurrentNode.ItemCount;

                //If the whole current node is below the minIndex, jump over it.
                if ((this.Index + (itemCount - 1)) < minIndex)
                {
                    processed = true;
                }

                //when the index to visit eNequeos the range defined, exit the loop.
                if (this.Index > maxIndex)
                {
                    break;
                }

                int minForNode = System.Math.Max(0, minIndex - this.Index);             // this will give the base offset within the node where to start the visitating!
                int maxForNode = System.Math.Min(itemCount - 1, maxIndex - this.Index); //this will five the max offset within this node to visit (protected against overlfow )

                if (!processed)
                {
                    HeadersFootersGeneratorNode headersNode = this.CurrentNode as HeadersFootersGeneratorNode;

                    if (headersNode != null)
                    {
                        bool isHeaderFooter = (headersNode.Parent == null);

                        //If the node is a Headers or Footers node AND the visitorType does not contain HeadersFooters
                        if ((isHeaderFooter) && ((visitorType & DataGridContextVisitorType.HeadersFooters) == DataGridContextVisitorType.HeadersFooters))
                        {
                            GeneratorNodeHelper.ProcessHeadersNodeVisit(headersNode, sourceContext, minForNode, maxForNode, visitor, ref visitWasStopped);
                        }
                        else if ((!isHeaderFooter) && ((visitorType & DataGridContextVisitorType.GroupHeadersFooters) == DataGridContextVisitorType.GroupHeadersFooters))
                        {
                            GeneratorNodeHelper.ProcessHeadersNodeVisit(headersNode, sourceContext, minForNode, maxForNode, visitor, ref visitWasStopped);
                        }

                        processed = true;
                    }
                }

                if (!processed)
                {
                    ItemsGeneratorNode itemsNode = this.CurrentNode as ItemsGeneratorNode;

                    if (itemsNode != null)
                    {
                        if ((visitorType & DataGridContextVisitorType.ItemsBlock) == DataGridContextVisitorType.ItemsBlock)
                        {
                            GeneratorNodeHelper.ProcessItemsNodeBlockVisit(
                                itemsNode, sourceContext,
                                minForNode, maxForNode,
                                visitor, visitorType, visitDetails, containsDetails, m_sourceDataIndex,
                                ref startSourceDataItemIndex, ref endSourceDataItemIndex, ref visitWasStopped);
                        }
                        else if (((visitDetails) && (containsDetails)) ||
                                 ((visitorType & DataGridContextVisitorType.Items) == DataGridContextVisitorType.Items))
                        {
                            GeneratorNodeHelper.ProcessItemsNodeVisit(
                                itemsNode, sourceContext,
                                minForNode, maxForNode,
                                visitor, visitorType, visitDetails, m_sourceDataIndex, ref visitWasStopped);
                        }

                        processed = true;
                    }
                }

                if (!processed)
                {
                    GroupGeneratorNode groupNode = this.CurrentNode as GroupGeneratorNode;

                    if (groupNode != null)
                    {
                        if ((visitorType & DataGridContextVisitorType.Groups) == DataGridContextVisitorType.Groups)
                        {
                            visitor.Visit(
                                sourceContext,
                                groupNode.CollectionViewGroup,
                                groupNode.NamesTree,
                                groupNode.Level,
                                groupNode.IsExpanded,
                                groupNode.IsComputedExpanded,
                                ref visitWasStopped);
                        }

                        processed = true;
                    }
                }

                if (!processed)
                {
                    throw new DataGridInternalException("Unable to process the visit.", sourceContext.DataGridControl);
                }

                if (visitWasStopped)
                {
                    break;
                }

                if (this.MoveToChild())
                {
                    continue;
                }

                if (this.MoveToFollowing())
                {
                    continue;
                }

                break;
            }while(true); //loop is controled by continue and break statements.


            if ((visitorType & DataGridContextVisitorType.ItemsBlock) == DataGridContextVisitorType.ItemsBlock)
            {
                if (startSourceDataItemIndex != -1)
                {
                    bool stopVisit = false;
                    visitor.Visit(sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit);
                    visitWasStopped = visitWasStopped || stopVisit;
                }
            }
        }
Exemple #24
0
        //This method cannot be used for groups.
        //This method will search for items independently of the Expanded/Collpased status of GroupGeneratorNodes
        public bool Contains(object item)
        {
            bool skipCollectionGeneratorNodeCheck = false;

            do
            {
                HeadersFootersGeneratorNode headersFootersNode = m_currentNode as HeadersFootersGeneratorNode;
                skipCollectionGeneratorNodeCheck = false;

                //If the node is a HeadersFootersGeneratorNode, do some specific handling.
                if (headersFootersNode != null)
                {
                    //If the item passed to the function is a GroupHeaderFooterItem, then its because we are looking for a GroupHeader/Footer
                    if (item.GetType() == typeof(GroupHeaderFooterItem))
                    {
                        GroupHeaderFooterItem groupHeaderFooterItem = ( GroupHeaderFooterItem )item;

                        //Determine the parent node/collectionViewGroup
                        GroupGeneratorNode parentGroup = headersFootersNode.Parent as GroupGeneratorNode;

                        if (parentGroup != null)
                        {
                            if (groupHeaderFooterItem.Group == parentGroup.CollectionViewGroup)
                            {
                                if (headersFootersNode.Items.Contains(groupHeaderFooterItem.Template))
                                {
                                    return(true);
                                }
                            }
                        }
                        //If there is no parent node, then its because the current HeadersFootersGeneratorNode is not a GroupHeaders/Footers node (FixedHeaders/Fotoers or Headers/Footers).

                        skipCollectionGeneratorNodeCheck = true; //force skip CollectionGeneratorNode verification, this is to limit amount of job done by loop body.
                    }

                    //If the item passed is not a GroupHeaderFooterItem, not need to do specific processing, reverting to "Common" algo.
                }

                if (!skipCollectionGeneratorNodeCheck)
                {
                    CollectionGeneratorNode collectionNode = m_currentNode as CollectionGeneratorNode;

                    if (collectionNode != null)
                    {
                        // When dealing with a DataView, the DataView's IList's Contains implementation will return false
                        // for a dataRowView which is in edition and was modified even though it is really part of the collection.
                        // Therefore, we must use a for loop of Object.Equals method calls.
                        System.Data.DataRowView dataRowViewItem = item as System.Data.DataRowView;

                        if (dataRowViewItem != null)
                        {
                            IList items      = collectionNode.Items;
                            int   itemsCount = items.Count;

                            System.Data.DataRow itemDataRow = dataRowViewItem.Row;

                            for (int i = 0; i < itemsCount; i++)
                            {
                                System.Data.DataRowView currentDataRowView = items[i] as System.Data.DataRowView;

                                if ((currentDataRowView != null) && (itemDataRow == currentDataRowView.Row))
                                {
                                    return(true);
                                }
                            }
                        }
                        else
                        {
                            //Since the GetAt() methods can be overriden to compensate for the Expand/Collapse status of Groups
                            // AND the details features, accessing the collection directly prevent pre-processing of the content of the collection node.
                            if (collectionNode.Items.Contains(item))
                            {
                                //if the item is from a detail, then I don't want to "use" it!!!
                                return(true);
                            }
                        }
                    }
                }

                //if we reach this point, it's because the item we are looking
                //for is not in this node... Try to access the child
                //Note: Since I want to search independently of the Expand/Collapse status,
                //pass false to the method to systematically visit childs.
                if (this.MoveToChild(false))
                {
                    continue;
                }

                //if we reach this point, it's because we have no child...
                if (this.MoveToNext())
                {
                    continue;
                }

                //final try, try "advancing" to the next item.
                if (this.MoveToFollowing())
                {
                    continue;
                }

                //up to this, we are in an endpoint, we failed.
                break;
            } while(true);

            return(false);
        }