internal static void AddChild(TreeViewItemViewModel parent, ModelItem item, object value, bool duplicatedNodeVisible, string childNodePrefix, ModelProperty trackingProperty) { // If necessary, evaluate uniqueness of given item bool isUnique = false; if (!duplicatedNodeVisible) { // Note: These evaluations expect item to be an immediate child of trackingProperty.Value // Intermediate nodes would for example undermine simple check just below // // Caveat 1: Aim is to greatly reduce, not to eliminate, display of nodes visible elsewhere // Caveat 1a: Nodes reachable from other isolated nodes are included in the collection // Caveat 1b: Nodes that are not isolated may be reachable from isolated nodes and thus // displayed together with the isolated ones; ShowPropertyInOutlineViewAsSiblingAttribute may make this seem normal // (If complete duplicate elimination were the aim, would likely need a "never expand" // display mode for duplicateNodeVisible=false children) // Caveat 2: Use of single uniqueChildren field may cause all children of a second // duplcatedNodeVisible=false property to be ignored if (fortunately only if) neither // property uses ShowPropertyInOutlineViewAttribute(true) -- that attribute's default // Caveat 3-n: Please see caveats described at top of UniqueModelItemHelper if (1 >= item.Parents.Count()) { isUnique = true; } else { // Avoided a thorough evaluation as long as we can if (null == parent.uniqueChildren) { parent.uniqueChildren = UniqueModelItemHelper.FindUniqueChildren(trackingProperty); } isUnique = parent.uniqueChildren.Contains(item); } } // If displayable now, create the view model node if (duplicatedNodeVisible || isUnique) { TreeViewItemViewModel child = TreeViewItemViewModel.CreateViewModel(parent, value); child.NodePrefixText = childNodePrefix; parent.AddChild(child, trackingProperty); } // Track for potential addition or removal of parents even if not presently visible if (!duplicatedNodeVisible) { ModelItemImpl itemImpl = item as ModelItemImpl; if (null != itemImpl) { ChangeNotificationTracker tracker = parent.GetTracker(trackingProperty); tracker.AddCollection(itemImpl.InternalParents); tracker.AddCollection(itemImpl.InternalSources); } } }
internal override void UpdateChildren(ChangeNotificationTracker tracker, EventArgs e) { if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewUpdateStart(); } base.UpdateChildren(tracker, e); tracker.CleanUp(); if (this.Value.Value != null) { this.AddChild(TreeViewItemViewModel.CreateViewModel(this, this.Value.Value), tracker.ParentProperty); } if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewUpdateEnd(); } }
internal override void LoadChildren() { if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewLoadChildrenStart(); } base.LoadChildren(); if (this.Value.Value != null) { ChangeNotificationTracker tracker = this.Parent.GetTracker(this); this.AddChild(TreeViewItemViewModel.CreateViewModel(this, this.Value.Value), tracker.ParentProperty); } if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewLoadChildrenEnd(); } }
internal static void AddModelProperty(TreeViewItemViewModel parent, ModelItem item, ModelProperty trackingProperty, ModelProperty property) { //in the case of multiple attributes, they go in this order //HidePropertyInOutlineViewAttribute //[item.ShowInOutlineViewAttribute.PromotedProperty = property.Name]. Set VisualValue by property and ignore itself. Usage ActivityDelegate, FlowStep. //ShowPropertyInOutlineViewAttribute //ShowPropertyInOutlineViewAsSiblingAttribute //ShowInOutlineViewAttribute ShowPropertyInOutlineViewAttribute viewChild = ExtensibilityAccessor.GetAttribute <ShowPropertyInOutlineViewAttribute>(property); if (ExtensibilityAccessor.GetAttribute <HidePropertyInOutlineViewAttribute>(property) != null) { //ignore return; } else if (IsPromotedProperty(item, property)) { if (property.IsCollection) { ModelItemCollection mc = property.Value as ModelItemCollection; AddModelItemCollection(parent, mc, trackingProperty); } else if (property.IsDictionary) { ModelItemDictionary dictionary = property.Dictionary; AddModelItemDictionary(parent, dictionary, trackingProperty); } else { parent.GetTracker(trackingProperty).Add(item, property); //if property.Value is null, then this would not add any node // Use promoted ModelItem's property to track, so pass null to AddModelItem method. AddModelItem(parent, property.Value, null); } } else if (viewChild != null) { if (viewChild.CurrentPropertyVisible) //property node visible { if (property.Value != null) { TreeViewItemViewModel childModel = TreeViewItemViewModel.CreateViewModel(parent, property); childModel.DuplicatedNodeVisible = viewChild.DuplicatedChildNodesVisible; parent.AddChild(childModel, trackingProperty); } else { //just add the notification tracker without adding the empty child parent.GetTracker(trackingProperty, true).Add(item, trackingProperty); } } else { if (property.IsCollection) { ModelItemCollection mc = property.Value as ModelItemCollection; AddModelItemCollection(parent, mc, trackingProperty); } else if (property.IsDictionary) { ModelItemDictionary dictionary = property.Dictionary; AddModelItemDictionary(parent, dictionary, trackingProperty); } else { if (property.Value != null) { TreeViewItemViewModel childModel = TreeViewItemViewModel.CreateViewModel(parent, property.Value); childModel.DuplicatedNodeVisible = viewChild.DuplicatedChildNodesVisible; parent.AddChild(childModel, trackingProperty); } else { parent.GetTracker(trackingProperty).Add(item, property); } } } } else if (ExtensibilityAccessor.GetAttribute <ShowPropertyInOutlineViewAsSiblingAttribute>(property) != null) { //add notification to the tracker that is responsible for this node ChangeNotificationTracker tracker = parent.Parent.GetTracker(parent); tracker.Add(item, property); TreeViewItemViewModel siblingNode = null; if (property.Value != null) { siblingNode = TreeViewItemViewModel.CreateViewModel(parent.Parent, property.Value); } parent.Parent.AddChild(siblingNode, tracker.ParentProperty); } else if (ExtensibilityAccessor.GetAttribute <ShowInOutlineViewAttribute>(property) != null) { if (property.Value != null) { ShowInOutlineViewAttribute outlineView = ExtensibilityAccessor.GetAttribute <ShowInOutlineViewAttribute>(property); if (string.IsNullOrWhiteSpace(outlineView.PromotedProperty)) { parent.AddChild(TreeViewItemViewModel.CreateViewModel(parent, property), trackingProperty); } else { ModelProperty promotedProperty = property.Value.Properties.Find(outlineView.PromotedProperty); if (promotedProperty == null) { throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.PromotedPropertyNotFound, outlineView.PromotedProperty, property.Value.Name))); } // Add promoted ModelItem and property into tracker. So when property got changed, the grandparent of promoted ModelItem will be notified. ChangeNotificationTracker tracker = parent.GetTracker(trackingProperty, true); tracker.Add(property.Value, promotedProperty); if (promotedProperty.Value == null) { tracker.Add(item, property); } else { parent.AddChild(TreeViewItemViewModel.CreateViewModel(parent, property), trackingProperty); } } } else { parent.GetTracker(trackingProperty, true).Add(item, property); } } //if the values in the dictionary is viewvisible, note this only works with generic dictionary else if (property.IsDictionary && property.PropertyType.IsGenericType) { Type[] arguments = property.PropertyType.GetGenericArguments(); if (ExtensibilityAccessor.GetAttribute <ShowInOutlineViewAttribute>(arguments[1]) != null) { if (property.Value != null) { parent.AddChild(TreeViewItemViewModel.CreateViewModel(parent, property), trackingProperty); } else { parent.GetTracker(trackingProperty, true).Add(item, property); } } } }