internal override int FindInsertionIndex(ChangeNotificationTracker tracker) { int insertionIndex = 0; if (tracker != null && (tracker.ChildViewModels == null || tracker.ChildViewModels.Count < 1)) { foreach (ModelProperty property in this.Value.Properties) { if (property != tracker.ParentProperty) { // assume this would increament ChangeNotificationTracker propertyTracker = this.GetTracker(property, false); if (propertyTracker != null) { insertionIndex = base.FindInsertionIndex(propertyTracker); } } else { // we've reach the property and hence the last of the previous property break; } } } else { insertionIndex = base.FindInsertionIndex(tracker); } return(insertionIndex); }
internal override void UpdateChildren(ChangeNotificationTracker tracker, EventArgs e) { if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewUpdateStart(); } // Update VisualValue when promotedProperty's got changed. if (this.promotedProperty != null && this.promotedProperty == tracker.ParentProperty) { this.VisualValue = this.promotedProperty.Value; } if (this.Children.Count == 1 && this.Children[0] == DummyNode) { // If the node never expanded before, LoadChildren instead of UpdateChildren. // Otherwise, when expanding node, the LoadChildren method won't invoke // Then other tracking properties cannot be setup correctly. this.InternalChildren.Remove(DummyNode); this.LoadChildren(); } else { // If requireUpdateChildren = false, the related TreeViewItemModelPropertyViewModel take care of updating child nodes. bool requireUpdateChildren = true; if (e is PropertyChangedEventArgs && this.IsModelPropertyNodeExisted(tracker.ParentProperty)) { ModelProperty modelProperty = tracker.ParentProperty; if (modelProperty.Value != null) { string changedPropertyName = ((PropertyChangedEventArgs)e).PropertyName; bool isPromotedPropertyChanged = TreeViewItemViewModel.IsPromotedProperty(modelProperty.Value, changedPropertyName); if (isPromotedPropertyChanged) { if (modelProperty.Value.Properties[changedPropertyName].Value != null) { requireUpdateChildren = false; } } else { requireUpdateChildren = false; } } } if (requireUpdateChildren) { base.UpdateChildren(tracker, e); tracker.CleanUp(); TreeViewItemViewModel.AddModelProperty(this, this.Value, tracker.ParentProperty, tracker.ParentProperty); } } if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewUpdateEnd(); } }
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 virtual int FindInsertionIndex(ChangeNotificationTracker tracker) { int insertIndex = 0; if (tracker != null && tracker.ChildViewModels != null && tracker.ChildViewModels.Count > 0) { //assume the childViewModels are in order insertIndex = this.InternalChildren.IndexOf(tracker.ChildViewModels.Last()) + 1; } return(insertIndex); }
internal virtual ChangeNotificationTracker GetTracker(ModelProperty modelProperty, bool createNew) { ChangeNotificationTracker tracker = null; if (!this.Trackers.TryGetValue(modelProperty, out tracker) && createNew) { tracker = new ChangeNotificationTracker(this, modelProperty); Trackers.Add(modelProperty, tracker); } return(tracker); }
internal ChangeNotificationTracker GetTracker(TreeViewItemViewModel child) { ChangeNotificationTracker trackerForChild = null; foreach (ChangeNotificationTracker tracker in this.Trackers.Values) { if (tracker.ChildViewModels.Contains(child)) { trackerForChild = tracker; break; } } Fx.Assert(trackerForChild != null, "Tracker should not be null"); return(trackerForChild); }
internal override ChangeNotificationTracker GetTracker(ModelProperty modelProperty, bool createNew) { ChangeNotificationTracker tracker = base.GetTracker(modelProperty, createNew); if (createNew) { Fx.Assert(this.Value == modelProperty, "The modelProperty should be the same as this.Value."); tracker.Add(modelProperty.Parent, modelProperty); ShowInOutlineViewAttribute viewVisible = ExtensibilityAccessor.GetAttribute <ShowInOutlineViewAttribute>(modelProperty); if (viewVisible != null && !string.IsNullOrWhiteSpace(viewVisible.PromotedProperty)) { ModelProperty promotedProperty = modelProperty.Value.Properties.Find(viewVisible.PromotedProperty); tracker.Add(promotedProperty.Parent, promotedProperty); } } return(tracker); }
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 UpdateChildren(ChangeNotificationTracker tracker, EventArgs e) { if (this.PerfEventProvider != null) { this.PerfEventProvider.DesignerTreeViewUpdateStart(); } // base.UpdateChildren(tracker, e); tracker.CleanUp(); this.InternalChildren.Clear(); this.LoadChildren(); 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 override ChangeNotificationTracker GetTracker(ModelProperty modelProperty, bool createNew) { ChangeNotificationTracker tracker = base.GetTracker(modelProperty, createNew); if (createNew) { if (this.VisualValue == modelProperty.Parent) { // If this TreeViewModelItem use Promopted property and the property belongs to Promoted activity // add the tracked property by default. tracker.Add(this.VisualValue, modelProperty); } else { // If it's an model item, add the tracked property by default tracker.Add(this.Value, modelProperty); } } return(tracker); }
//if child is null then only add the modelProperty for tracking purpose internal virtual void AddChild(TreeViewItemViewModel child, ModelProperty modelProperty) { //check for duplicate first if (child != null) { object childValue = child.GetValue(); if (!ChildrenValueCache.Contains(childValue)) { ChildrenValueCache.Add(childValue); } else { child.CleanUp(); return; } } ChangeNotificationTracker tracker = GetTracker(modelProperty); if (child != null) { // May be adding a node before it's expanded; get rid of the dummy if (this.Children.Count == 1 && this.Children[0] == DummyNode) { this.InternalChildren.Remove(DummyNode); } int insertIndex = this.FindInsertionIndex(tracker); this.InternalChildren.Insert(insertIndex, child); tracker.ChildViewModels.Add(child); if (child.HasSibling) { //loading children rather than just add the sibling of the children //if this turn out to be a big performance impact then we'll need to optimise this child.LoadChildren(); } } }
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); } } } }
internal virtual void UpdateChildren(ChangeNotificationTracker tracker, EventArgs e) { this.uniqueChildren = null; }
internal virtual void UpdateChildren(ChangeNotificationTracker tracker, EventArgs e) { this.uniqueChildren = null; }
internal virtual int FindInsertionIndex(ChangeNotificationTracker tracker) { int insertIndex = 0; if (tracker != null && tracker.ChildViewModels != null && tracker.ChildViewModels.Count > 0) { //assume the childViewModels are in order insertIndex = this.InternalChildren.IndexOf(tracker.ChildViewModels.Last()) + 1; } return insertIndex; }
internal virtual ChangeNotificationTracker GetTracker(ModelProperty modelProperty, bool createNew) { ChangeNotificationTracker tracker = null; if (!this.Trackers.TryGetValue(modelProperty, out tracker) && createNew) { tracker = new ChangeNotificationTracker(this, modelProperty); Trackers.Add(modelProperty, tracker); } return tracker; }