/// <summary>
        ///     Callback from DescendentsWalker before the nodes children are visited.
        /// </summary>
        /// <param name="dependencyObject">node to visit</param>
        /// <param name="data">data used for the current tree walk</param>
        /// <returns>returns whether or not the children should be visited</returns>
        private bool PreVisit(DependencyObject dependencyObject, ProcessingTreeState data, bool visitedViaVisualTree)
        {
            Debug.Assert(data != null, "dataBlob is either null or not of ProcessingTreeState type");
            
            bool calledProcessAnnotations = false;

            SubTreeProcessor processor = GetSubTreeProcessor(dependencyObject);
            Debug.Assert(processor != null, "SubtreeProcessor can not be null"); // There is always a default processor

            IList<IAttachedAnnotation> attachedAnnotations = processor.PreProcessNode(dependencyObject, out calledProcessAnnotations);
            if (attachedAnnotations != null)
                data.AttachedAnnotations.AddRange(attachedAnnotations);                

            // Combine whether this processor called ProcessAnnotations with the info of its siblings
            data.CalledProcessAnnotations = data.CalledProcessAnnotations || calledProcessAnnotations;
            data.Push();

            // Returning true here prevents children from being called
            return !calledProcessAnnotations;
        }
        /// <summary>
        ///     Callback from DescendentsWalker after the nodes children are visited.
        /// </summary>
        /// <param name="dependencyObject">node to visit</param>
        /// <param name="data">data used for the current tree walk</param>
        /// <returns>return value is ignored</returns>
        private bool PostVisit(DependencyObject dependencyObject, ProcessingTreeState data, bool visitedViaVisualTree)
        {
            Debug.Assert(data != null, "dataBlob is either null or not of ProcessingTreeState type");

            bool childrenCalledProcessAnnotations = data.Pop();
            SubTreeProcessor processor = GetSubTreeProcessor(dependencyObject);
            Debug.Assert(processor != null, "SubtreeProcessor can not be null");

            bool calledProcessAnnotations = false;
            IList<IAttachedAnnotation> attachedAnnotations = processor.PostProcessNode(dependencyObject, childrenCalledProcessAnnotations, out calledProcessAnnotations);
            if (attachedAnnotations != null)
                data.AttachedAnnotations.AddRange(attachedAnnotations);

            // This flag is information available to PostVisit calls
            data.CalledProcessAnnotations = data.CalledProcessAnnotations || calledProcessAnnotations || childrenCalledProcessAnnotations;

            // This return value is not used by PrePostDescendentsWalker
            return true;
        }
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        
        /// <summary>
        ///     Traverse the element tree starting at subtree and load
        ///     annotations for that subtree.
        /// </summary>
        /// <param name="subTree">root of the subtree for which to load annotations</param>
        /// <returns>list of IAttachedAnnotations that were loaded for 'node';
        /// the list will never be null but may be empty</returns>
        /// <exception cref="ArgumentNullException">subtree is null</exception>
        internal IList<IAttachedAnnotation> ProcessSubTree(DependencyObject subTree)
        {
            if (subTree == null)
                throw new ArgumentNullException("subTree");

            ProcessingTreeState data = new ProcessingTreeState();
            PrePostDescendentsWalker<ProcessingTreeState> walker = new PrePostDescendentsWalker<ProcessingTreeState>(TreeWalkPriority.VisualTree, PreVisit, PostVisit, data);
            walker.StartWalk(subTree);

            return data.AttachedAnnotations;
        }