// <summary>
        // Creates an instance of SelectionPath to the specified category container's
        // basic or advanced sections that this class knows how to interpret.
        // </summary>
        // <param name="categoryName">Name of the category</param>
        // <param name="isAdvanced">True if the path should lead to the advanced section,
        // false otherwise.</param>
        // <returns>A new instance of SelectionPath to the specified section of the specified
        // category container.</returns>
        public SelectionPath ConstructSelectionPath(string categoryName, bool isAdvanced)
        {
            StringBuilder path = new StringBuilder(PersistedStateUtilities.Escape(categoryName));

            if (isAdvanced)
            {
                path.Append(",Advanced");
            }

            return(new SelectionPath(PathTypeId, path.ToString()));
        }
        // ISelectionPathInterpreter Members

        public DependencyObject ResolveSelectionPath(CategoryList root, SelectionPath path, out bool pendingGeneration)
        {
            pendingGeneration = false;
            if (path == null || !string.Equals(PathTypeId, path.PathTypeId))
            {
                Debug.Fail("Invalid SelectionPath specified.");
                return(null);
            }

            if (root == null)
            {
                Debug.Fail("No CategoryList specified.");
                return(null);
            }

            string[] pathValues   = path.Path.Split(',');
            string   categoryName = PersistedStateUtilities.Unescape(pathValues[0]);
            bool     isAdvanced   = pathValues.Length == 2;

            CategoryEntry category = root.FindCategory(categoryName);

            if (category == null)
            {
                return(null);
            }

            DependencyObject categoryVisual = root.FindCategoryEntryVisual(category);

            if (categoryVisual == null)
            {
                return(null);
            }

            DependencyObject searchStart;

            // For basic section, start at the root.
            // For advanced section, start at the advanced expander.
            // The next SelectionStop in both cases will be the section header SelectionStop.
            if (!isAdvanced)
            {
                searchStart = categoryVisual;
            }
            else
            {
                searchStart = VisualTreeUtils.GetNamedChild <FrameworkElement>(categoryVisual, "PART_AdvancedExpander");
            }

            return(PropertySelection.FindNeighborSelectionStop <DependencyObject>(searchStart, SearchDirection.Next));
        }
        // ISelectionPathInterpreter Members

        public DependencyObject ResolveSelectionPath(CategoryList root, SelectionPath path, out bool pendingGeneration)
        {
            pendingGeneration = false;
            if (path == null || !string.Equals(PathTypeId, path.PathTypeId))
            {
                Debug.Fail("Invalid SelectionPath specified.");
                return(null);
            }

            if (root == null)
            {
                Debug.Fail("No CategoryList specified.");
                return(null);
            }

            string[] pathValues = path.Path.Split(',');
            if (pathValues.Length < 1)
            {
                Debug.Fail("Invalid SelectionPath specified.");
                return(null);
            }

            //
            // Note: By the time this method gets called, all the visuals should have been expanded
            // and rendered.  Hence, if we can't find a visual in the visual tree, it doesn't exist
            // and we shouldn't worry about trying to expand some parent visual and waiting for it
            // to render.
            //

            ModelCategoryEntry parentCategory;

            PropertyEntry     currentProperty    = root.FindPropertyEntry(PersistedStateUtilities.Unescape(pathValues[0]), out parentCategory);
            PropertyContainer currentContainer   = root.FindPropertyEntryVisual(currentProperty, parentCategory, out pendingGeneration);
            DependencyObject  lastFoundContainer = currentContainer;
            int pathIndex = 1;

            while (currentContainer != null && pathIndex < pathValues.Length)
            {
                SubPropertyEditor subPropertyEditor = VisualTreeUtils.GetTemplateChild <SubPropertyEditor>(currentContainer);
                if (subPropertyEditor == null)
                {
                    break;
                }

                // If the subpropertyEditor is not expanded and is expandable, we won't be able to get the target property's visual
                // element, Expand it, set pendingGeneration to True, and return null. Expect the caller to call again.
                if (subPropertyEditor.IsExpandable && !subPropertyEditor.IsExpanded)
                {
                    subPropertyEditor.IsExpanded = true;
                    pendingGeneration            = true;
                    return(null);
                }

                PropertyEntry property = subPropertyEditor.FindSubPropertyEntry(PersistedStateUtilities.Unescape(pathValues[pathIndex]));
                if (property == null)
                {
                    break;
                }

                currentContainer   = subPropertyEditor.FindSubPropertyEntryVisual(property);
                lastFoundContainer = currentContainer ?? lastFoundContainer;
                pathIndex++;
            }

            if (lastFoundContainer == null)
            {
                return(null);
            }

            return(lastFoundContainer);
        }