// Tries to figure out what property to select and selects is
        private void UpdateSelectedProperty(View.Selection selection)
        {
            // If we are not loaded, skip any and all selection magic
            if (!this.IsLoaded)
            {
                return;
            }

            if (selection != null)
            {
                // See what the view would like us to select if we run out of things
                // we can think of selecting
                //
                SelectionPath fallbackSelection = null;
                if (_propertyToolBar.CurrentViewManager != null)
                {
                    fallbackSelection = _propertyToolBar.CurrentViewManager.GetDefaultSelectionPath(_categoryList);
                }

                // Select the first thing we request that exists, using the following
                // precedence order:
                //
                //  * LastSelectionPath
                //  * DefaultProperty
                //  * Whatever the view wants to show (first category, first property, ...)
                //
                _categoryList.UpdateSelectedProperty(
                    this.LastSelectionPath,
                    ModelPropertyMerger.GetMergedDefaultProperty(selection.SelectedObjects),
                    fallbackSelection);
            }

            if (DesignerPerfEventProvider != null)
            {
                DesignerPerfEventProvider.PropertyInspectorUpdatePropertyListEnd();
            }
        }
        // This is the work-horse that refreshes the list of properties and categories within a PropertyInspector
        // window, including refreshing of CategoryEditors, based on the specified selection
        private void UpdateCategories(View.Selection selection, bool attachedOnly)
        {
            // Optimization stolen from Sparkle:
            // re-rendering the categories is the number one perf issue. Clearing
            // the databound collection results in massive Avalon code execution, and
            // then re-adding everything causes another huge shuffle. What is more,
            // even when changing the selection between different objects, most properties
            // do not change. Therefore we are going to take the new list of properties
            // and we are going to merge them into the existing stuff, using an
            // approach I call Mark, Match, and Cull.
            //
            // First we mark all the properties in the current collection. Those which
            // are still marked at the end will be culled out
            foreach (ModelCategoryEntry category in _categoryList)
            {
                if (attachedOnly)
                {
                    category.MarkAttachedPropertiesDisassociated();
                }
                else
                {
                    category.MarkAllPropertiesDisassociated();
                }
            }

            // Second we try to match each property in the list of properties for the newly selected objects
            // against something that we already have. If we have a match, then we reset the existing
            // ModelPropertyEntry and clear the mark
            //
            foreach (IEnumerable <ModelProperty> propertySet in
                     ModelPropertyMerger.GetMergedProperties(
                         selection == null ? null : selection.SelectedObjects,
                         selection == null ? 0 : selection.SelectionCount))
            {
                string propertyName = GetPropertyName(propertySet);

                // Specifically filter out the Name property
                // PS 40699 - Name is not a special property for WF
                //if ("Name".Equals(propertyName))
                //{
                //    continue;
                //}

                if (attachedOnly && propertyName.IndexOf('.') < 0)
                {
                    continue;
                }

                ModelPropertyEntry wrappedProperty = _propertyToolBar.CurrentViewManager.AddProperty(propertySet, propertyName, _categoryList);

                // Make sure no valid properties get culled out
                wrappedProperty.Disassociated = false;
            }

            // Third, we walk the properties and categories, and we cull out all of the
            // marked properties. Empty categories are removed.
            //
            for (int i = _categoryList.Count - 1; i >= 0; i--)
            {
                ModelCategoryEntry category = (ModelCategoryEntry)_categoryList[i];
                category.CullDisassociatedProperties();
                if (category.IsEmpty)
                {
                    _categoryList.RemoveAt(i);
                }
            }

            _categoryList.RefreshFilter();
        }