public CategoryContainerItemAutomationPeer( ModelCategoryEntry item, CiderCategoryContainer container, CategoryListAutomationPeer parentAutomationPeer) : base(item, parentAutomationPeer) { _coreLogic = new CategoryContainerAutomationPeer(container, this); _coreLogic.AddFocusEvents(); }
// IPropertyViewManager Members // <summary> // Add a property into the correct category within the specified CategoryList. // </summary> // <param name="propertySet">Specified property (passed in as a set for multi-select scenarios)</param> // <param name="propertyName">Name of the current property (perf optimization)</param> // <param name="categoryList">CategoryList instance to populate</param> // <returns>Wrapped ModelPropertyEntry for the specified propertySet</returns> public ModelPropertyEntry AddProperty(IEnumerable <ModelProperty> propertySet, string propertyName, CategoryList categoryList) { string categoryName = GetCategoryName(propertySet); ModelCategoryEntry category = categoryList.FindCategory(categoryName) as ModelCategoryEntry; bool reuseEntries = ExtensibilityAccessor.IsEditorReusable(propertySet); if (reuseEntries && category != null) { ModelPropertyEntry foundProperty; if ((foundProperty = (ModelPropertyEntry)category[propertyName]) != null) { if (foundProperty.PropertyType != null && foundProperty.PropertyType.Equals(System.Activities.Presentation.Internal.PropertyEditing.Model.ModelUtilities.GetPropertyType(propertySet))) { // Found a match for the property, so reuse it bool oldIsBrowsable = foundProperty.IsBrowsable; bool oldIsAdvanced = foundProperty.IsAdvanced; foundProperty.SetUnderlyingModelProperty(propertySet); // If the IsBrowsable or IsAdvanced value of the property changed, // refresh the property within the category, because how and whether // this property should be rendered may have changed. // Note that refreshing a selected property also nullifies its stickiness // (ie. it resets CategoryList.PropertySelectionMode) if (oldIsAdvanced != foundProperty.IsAdvanced || oldIsBrowsable != foundProperty.IsBrowsable) { category.Refresh(foundProperty, category.GetBucket(foundProperty), this.PropertyComparer); } return(foundProperty); } } } if (category == null) { category = new ModelCategoryEntry(categoryName); categoryList.InsertAlphabetically(category); } ModelPropertyEntry property = new ModelPropertyEntry(propertySet, null); category.Add(property, category.GetBucket(property), this.PropertyComparer); return(property); }
// Find the first CategoryEditor that consumes the specified property in the specified category. // private static CategoryEditor FindCategoryEditor(PropertyEntry property, ModelCategoryEntry parentCategory) { if (property == null || parentCategory == null) { return(null); } foreach (CategoryEditor editor in parentCategory.CategoryEditors) { if (editor.ConsumesProperty(property)) { return(editor); } } return(null); }
// <summary> // Looks for and returns the UIElement used to represent the specified CategoryEditor. Returns // null if not found. // </summary> // <param name="editor">CategoryEditor to look for.</param> // <param name="category">Category to look in.</param> // <param name="pendingGeneration">Set to true if the specified editor exists in a collapsed container // (CategoryContainer or an advanced section). If so, the section is expanded, but the visual does not // exist yet and should be requested later.</param> // <returns>UIElement for the specified CategoryEditor if found, null otherwise</returns> internal UIElement FindCategoryEditorVisual(CategoryEditor editor, ModelCategoryEntry category, out bool pendingGeneration) { pendingGeneration = false; if (editor == null || category == null) { return(null); } UIElement editorVisual = null; CiderCategoryContainer categoryContainer = this.ItemContainerGenerator.ContainerFromItem(category) as CiderCategoryContainer; if (categoryContainer == null) { return(null); } // Expand the parent category, if it isn't already if (!categoryContainer.Expanded) { categoryContainer.Expanded = true; pendingGeneration = true; } // Expand the parent advanced section, if any and if it isn't already if (!categoryContainer.AdvancedSectionPinned && ExtensibilityAccessor.GetIsAdvanced(editor)) { categoryContainer.AdvancedSectionPinned = true; pendingGeneration = true; } bool pendingGenerationTemp; editorVisual = categoryContainer.ContainerFromEditor(editor, out pendingGenerationTemp); pendingGeneration |= pendingGenerationTemp; if (editorVisual != null) { pendingGeneration = false; } return(editorVisual); }
// Check if the category is shown for the current category editor type private bool IsCategoryShown(Type categoryEditorType) { bool ret = true; CategoryEditor editorToRemove = (CategoryEditor)ExtensibilityAccessor.SafeCreateInstance(categoryEditorType); if (editorToRemove != null) { ModelCategoryEntry affectedCategory = _categoryList.FindCategory(editorToRemove.TargetCategory) as ModelCategoryEntry; if (affectedCategory == null) { ret = false; } } else { ret = false; } return(ret); }
// <summary> // Looks for the PropertyEntry and its parent CategoryEntry for the specified property // </summary> // <param name="propertyName">Property to look for</param> // <param name="parentCategory">Parent CategoryEntry of the given property</param> // <returns>Corresponding PropertyEntry if found, null otherwise.</returns> internal PropertyEntry FindPropertyEntry(string propertyName, out ModelCategoryEntry parentCategory) { parentCategory = null; if (propertyName == null) { return(null); } foreach (ModelCategoryEntry category in this.Items) { PropertyEntry property = category[propertyName]; if (property != null) { parentCategory = category; return(property); } } return(null); }
// <summary> // Looks for the CategoryEditor of the specified type and returns it if found. // </summary> // <param name="editorTypeName">Type name of the editor to look for.</param> // <param name="category">CategoryEntry that the editor belongs to, if found.</param> // <returns>CategoryEditor instance of the given type name if found, null otherwise.</returns> internal CategoryEditor FindCategoryEditor(string editorTypeName, out ModelCategoryEntry category) { category = null; if (string.IsNullOrEmpty(editorTypeName) || this.Items == null) { return(null); } foreach (ModelCategoryEntry currentCategory in this.Items) { foreach (CategoryEditor editor in currentCategory.CategoryEditors) { if (string.Equals(editorTypeName, editor.GetType().Name)) { category = currentCategory; return(editor); } } } return(null); }
// <summary> // Creates a CategoryContainerAutomationPeer that can be returned for CategoryContainers // belonging to a CategoryList control // </summary> // <param name="category">CategoryEntry instance used by ItemsControl</param> // <param name="container">Container to automate</param> // <param name="parentAutomationPeer">Parent AutomationPeer</param> // <returns>Instance of CategoryContainerAutomationPeer that can be returned for CategoryContainers // belonging to a CategoryList control</returns> public static ItemAutomationPeer CreateItemAutomationPeer(ModelCategoryEntry category, CiderCategoryContainer container, CategoryListAutomationPeer parentAutomationPeer) { return(new CategoryContainerItemAutomationPeer(category, container, parentAutomationPeer)); }
// Helper method that adjusts the visible set of CategoryEditors based on the specified selection private void UpdateCategoryEditors(View.Selection selection) { // Figure out which category editors to show Dictionary <Type, object> newCategoryEditorTypes = _propertyToolBar.CurrentViewManager.GetCategoryEditors( FindCommonType(selection == null ? null : selection.SelectedObjects), _categoryList); // Figure out which CategoryEditors are no longer needed and remove them List <Type> editorTypesToRemove = null; foreach (KeyValuePair <Type, string> item in _activeCategoryEditors) { if (!newCategoryEditorTypes.ContainsKey(item.Key) || !IsCategoryShown(item.Key)) { // New selection does not include this existing category editor // or the category that contains this editor // so remove the editor. if (editorTypesToRemove == null) { editorTypesToRemove = new List <Type>(); } editorTypesToRemove.Add(item.Key); } else { // This category editor already exists, so don't re-add it newCategoryEditorTypes.Remove(item.Key); } } if (editorTypesToRemove != null) { foreach (Type editorTypeToRemove in editorTypesToRemove) { ModelCategoryEntry affectedCategory = _categoryList.FindCategory(_activeCategoryEditors[editorTypeToRemove]) as ModelCategoryEntry; if (affectedCategory != null) { affectedCategory.RemoveCategoryEditor(editorTypeToRemove); } _activeCategoryEditors.Remove(editorTypeToRemove); } } // Figure out which CategoryEditors are now required and add them foreach (Type editorTypeToAdd in newCategoryEditorTypes.Keys) { CategoryEditor editor = (CategoryEditor)ExtensibilityAccessor.SafeCreateInstance(editorTypeToAdd); if (editor == null) { continue; } ModelCategoryEntry affectedCategory = _categoryList.FindCategory(editor.TargetCategory) as ModelCategoryEntry; if (affectedCategory == null) { continue; } affectedCategory.AddCategoryEditor(editor); _activeCategoryEditors[editorTypeToAdd] = editor.TargetCategory; } }
// 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(); }
// <summary> // Adds the specified property into the specified category. // </summary> // <param name="property">Property to add</param> // <param name="category">Category to populate</param> public void AddProperty(PropertyEntry property, ModelCategoryEntry category) { category.Add(property as ModelPropertyEntry, category.GetBucket(property), this.PropertyComparer); }
// <summary> // Adds the specified property into the specified category. // </summary> // <param name="property">Property to add</param> // <param name="category">Category to populate</param> public void AddProperty(PropertyEntry property, ModelCategoryEntry category) { category.Add(property, category.BasicProperties, this.PropertyComparer); }