// Token: 0x06000C62 RID: 3170 RVA: 0x0002E35C File Offset: 0x0002C55C private static bool OnAncestorChanged(DependencyObject d, TreeChangeInfo info, bool visitedViaVisualTree) { FrameworkObject frameworkObject = new FrameworkObject(d, true); TreeWalkHelper.OnAncestorChanged(frameworkObject.FE, frameworkObject.FCE, info); return(true); }
internal void OnAncestorChangedInternal(TreeChangeInfo parentTreeState) { // Cache the IsSelfInheritanceParent flag bool wasSelfInheritanceParent = IsSelfInheritanceParent; if (parentTreeState.Root != this) { // Clear the HasStyleChanged flag HasStyleChanged = false; HasStyleInvalidated = false; } // If this is a tree add operation update the ShouldLookupImplicitStyles // flag with respect to your parent. if (parentTreeState.IsAddOperation) { FrameworkObject fo = new FrameworkObject(null, this); fo.SetShouldLookupImplicitStyles(); } // Invalidate ResourceReference properties if (HasResourceReference) { // This operation may cause a style change and hence should be done before the call to // InvalidateTreeDependents as it relies on the HasStyleChanged flag TreeWalkHelper.OnResourcesChanged(this, ResourcesChangeInfo.TreeChangeInfo, false); } // If parent is a FrameworkElement // This is also an operation that could change the style FrugalObjectList <DependencyProperty> currentInheritableProperties = InvalidateTreeDependentProperties(parentTreeState, IsSelfInheritanceParent, wasSelfInheritanceParent); // we have inherited properties that changes as a result of the above; // invalidation; push that list of inherited properties on the stack // for the children to use parentTreeState.InheritablePropertiesStack.Push(currentInheritableProperties); // Notify the PresentationSource that this element's ancestry may have changed. // We only need the ContentElement's because UIElements are taken care of // through the Visual class. PresentationSource.OnAncestorChanged(this); // Call OnAncestorChanged OnAncestorChanged(); // Notify mentees if they exist if (PotentiallyHasMentees) { // Raise the ResourcesChanged Event so that ResourceReferenceExpressions // on non-[FE/FCE] listening for this can then update their values RaiseClrEvent(FrameworkElement.ResourcesChangedKey, EventArgs.Empty); } }
// Token: 0x06000C64 RID: 3172 RVA: 0x0002E39B File Offset: 0x0002C59B private static bool OnPostAncestorChanged(DependencyObject d, TreeChangeInfo info, bool visitedViaVisualTree) { if (info.TopmostCollapsedParentNode == d) { info.TopmostCollapsedParentNode = null; } info.InheritablePropertiesStack.Pop(); return(true); }
// Token: 0x06000C66 RID: 3174 RVA: 0x0002E490 File Offset: 0x0002C690 private static bool InvalidateTreeDependentProperty(TreeChangeInfo info, DependencyObject d, ref FrameworkObject fo, DependencyProperty dp, FrameworkPropertyMetadata fMetadata, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent, bool wasSelfInheritanceParent) { if (!TreeWalkHelper.SkipNext(fo.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { InheritablePropertyChangeInfo rootInheritableValue = info.GetRootInheritableValue(dp); EffectiveValueEntry oldEntry = rootInheritableValue.OldEntry; EffectiveValueEntry effectiveValueEntry = info.IsAddOperation ? rootInheritableValue.NewEntry : new EffectiveValueEntry(dp, BaseValueSourceInternal.Inherited); bool flag = TreeWalkHelper.IsForceInheritedProperty(dp); if (d != info.Root) { if (wasSelfInheritanceParent) { oldEntry = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); } else if (isSelfInheritanceParent) { EffectiveValueEntry valueEntry = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); if (valueEntry.BaseValueSourceInternal <= BaseValueSourceInternal.Inherited) { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } else { oldEntry = valueEntry; } } else { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else if (info.IsAddOperation && (flag || oldEntry.BaseValueSourceInternal <= BaseValueSourceInternal.Inherited)) { EffectiveValueEntry valueEntry2 = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); if (valueEntry2.BaseValueSourceInternal > BaseValueSourceInternal.Inherited) { oldEntry = valueEntry2; } } OperationType operationType = info.IsAddOperation ? OperationType.AddChild : OperationType.RemoveChild; if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { return((d.UpdateEffectiveValue(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref effectiveValueEntry, false, false, operationType) & (UpdateResult)5) == UpdateResult.ValueChanged); } if (flag) { effectiveValueEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); return((d.UpdateEffectiveValue(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref effectiveValueEntry, false, false, operationType) & (UpdateResult)5) == UpdateResult.ValueChanged); } } return(false); }
/// <summary> /// This is called when the PrePostDescendentsWalker is done with the given /// node and its subtree. /// </summary> private static bool OnPostAncestorChanged( DependencyObject d, TreeChangeInfo info) { // If the given node is the root of a collapsed subtree, we're // done with that subtree now and from this point forward, the given // node is not the "topmost collapsed parent node". // InvalidateTreeDependentProperties sets this reference when // appropriate, and OnPropertyChanged uses it to bypass // layout invalidation when in a collapsed subtree. if (info.TopmostCollapsedParentNode == d) { info.TopmostCollapsedParentNode = null; } // a return of true indicates that there was a cache set for this // node (meaning this node wasn't a leaf); // so pop the InheritableProperties cache for this node info.InheritablePropertiesStack.Pop(); return true; }
private static void OnAncestorChanged( FrameworkElement fe, FrameworkContentElement fce, TreeChangeInfo info) { if (fe!= null) { fe.OnAncestorChangedInternal(info); } else { fce.OnAncestorChangedInternal(info); } }
/// <summary> /// Callback on visiting each node in the descendency during a tree change /// Note that this is only used in an entire sub-tree undergoes a change. /// If the tree change is happening on a single node with no children, this /// invalidation happens inside InvalidateOnTreeChange and this method doesn't /// get involved. /// </summary> private static bool OnAncestorChanged( DependencyObject d, TreeChangeInfo info) { // Invalidate properties on current instance FrameworkObject fo = new FrameworkObject(d, true); OnAncestorChanged(fo.FE, fo.FCE, info); // Continue walk down subtree return true; }
// Invalidate all the properties that may have changed as a result of // changing this element's parent in the logical (and sometimes visual tree.) internal FrugalObjectList <DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, bool isSelfInheritanceParent, bool wasSelfInheritanceParent) { AncestorChangeInProgress = true; try { // Style property is a special case of a non-inherited property that needs // invalidation for parent changes. Invalidate StyleProperty if it hasn't been // locally set because local value takes precedence over implicit references if (!HasLocalStyle && (this != parentTreeState.Root)) { UpdateStyleProperty(); } Style selfStyle = null; Style selfThemeStyle = null; DependencyObject templatedParent = null; int childIndex = -1; ChildRecord childRecord = new ChildRecord(); bool isChildRecordValid = false; selfStyle = Style; selfThemeStyle = ThemeStyle; templatedParent = TemplatedParent; childIndex = TemplateChildIndex; // StyleProperty could have changed during invalidation of ResourceReferenceExpressions if it // were locally set or during the invalidation of unresolved implicitly referenced style bool hasStyleChanged = HasStyleChanged; // Fetch selfStyle, hasStyleChanged and childIndex for the current node FrameworkElement.GetTemplatedParentChildRecord(templatedParent, childIndex, out childRecord, out isChildRecordValid); FrameworkElement parentFE; FrameworkContentElement parentFCE; bool hasParent = FrameworkElement.GetFrameworkParent(this, out parentFE, out parentFCE); DependencyObject parent = null; InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (hasParent) { if (parentFE != null) { parent = parentFE; parentInheritanceBehavior = parentFE.InheritanceBehavior; } else { parent = parentFCE; parentInheritanceBehavior = parentFCE.InheritanceBehavior; } } if (!TreeWalkHelper.SkipNext(InheritanceBehavior) && !TreeWalkHelper.SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent this.SynchronizeInheritanceParent(parent); } else if (!IsSelfInheritanceParent) { // Set IsSelfInheritanceParet on the root node at a tree boundary // so that all inheritable properties are cached on it. SetIsSelfInheritanceParent(); } // Loop through all cached inheritable properties for the parent to see if they should be invalidated. return(TreeWalkHelper.InvalidateTreeDependentProperties(parentTreeState, /* fe = */ null, /* fce = */ this, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent, wasSelfInheritanceParent)); } finally { AncestorChangeInProgress = false; } }
internal void OnAncestorChangedInternal(TreeChangeInfo parentTreeState) { // Cache the IsSelfInheritanceParent flag bool isSelfInheritanceParent = IsSelfInheritanceParent; if (parentTreeState.Root != this) { // Clear the HasStyleChanged flag HasStyleChanged = false; HasStyleInvalidated = false; } // If this is a tree add operation update the ShouldLookupImplicitStyles // flag with respect to your parent. if (parentTreeState.IsAddOperation) { FrameworkObject fo = new FrameworkObject(null, this); fo.SetShouldLookupImplicitStyles(); } // Invalidate ResourceReference properties if (HasResourceReference) { // This operation may cause a style change and hence should be done before the call to // InvalidateTreeDependents as it relies on the HasStyleChanged flag TreeWalkHelper.OnResourcesChanged(this, ResourcesChangeInfo.TreeChangeInfo, false); } // If parent is a FrameworkElement // This is also an operation that could change the style FrugalObjectList<DependencyProperty> currentInheritableProperties = InvalidateTreeDependentProperties(parentTreeState, isSelfInheritanceParent); // we have inherited properties that changes as a result of the above; // invalidation; push that list of inherited properties on the stack // for the children to use parentTreeState.InheritablePropertiesStack.Push(currentInheritableProperties); // Notify the PresentationSource that this element's ancestry may have changed. // We only need the ContentElement's because UIElements are taken care of // through the Visual class. PresentationSource.OnAncestorChanged(this); // Call OnAncestorChanged OnAncestorChanged(); // Notify mentees if they exist if (PotentiallyHasMentees) { // Raise the ResourcesChanged Event so that ResourceReferenceExpressions // on non-[FE/FCE] listening for this can then update their values RaiseClrEvent(FrameworkElement.ResourcesChangedKey, EventArgs.Empty); } }
/// <summary> /// Invalidate inheritable properties and resource /// references during a tree change operation. /// </summary> internal static void InvalidateOnTreeChange( FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, bool isAddOperation) { Debug.Assert(fe != null || fce != null, "Node with the tree change notification must be an FE or an FCE."); Debug.Assert(parent != null, "Must have a parent that the current node is connected to or disconnected from."); // If the tree change is for a non-FE/FCE parent then we need to find // the nearest FE/FCE parent inorder to propagate inheritance correctly. FrameworkObject parentFO = new FrameworkObject(parent); if (!parentFO.IsValid) { parent = parentFO.FrameworkParent.DO; } // We're interested in changes to the Template property that occur during // the walk - if the template has changed we don't need to invalidate // template-driven properties a second time. The HasTemplateChanged property // is cleared on the first visit to each node, so that it means "template // changed during the walk". But one relevant node isn't visited during // the walk - the templated parent of the initial node. So we handle that now. FrameworkObject fo = new FrameworkObject(fe, fce); // Synchronize the ShouldLookupImplicitStyles flag with respect to the parent here // because for the root node of a tree change UpdateStyleProperty happens right here // in this method. And we need to have synchrnozed the ShouldLookupImplicitStyles // before we re-query the Style property. if (isAddOperation) { fo.SetShouldLookupImplicitStyles(); } fo.Reset(fo.TemplatedParent); fo.HasTemplateChanged = false; DependencyObject d = (fe != null) ? (DependencyObject)fe : (DependencyObject)fce; // during a tree walk to invalidate inherited properties, we typically // call UpdateStyle from FE/FCE.InvalidateTreeDependentProperties. But // for the root element of the tree change, we need to record old values // for inherited properties before we've updated the inheritance parent; // so do the updatestyle here before we record old values so that we // capture any updates provided by styles. if (fe != null) { if (fe.IsInitialized && !fe.HasLocalStyle) { // Clear the HasStyleChanged flag fe.HasStyleChanged = false; fe.HasStyleInvalidated = false; fe.HasTemplateChanged = false; fe.AncestorChangeInProgress = true; fe.UpdateStyleProperty(); fe.AncestorChangeInProgress = false; } } else { if (!fce.HasLocalStyle) { // Clear the HasStyleChanged flag fce.HasStyleChanged = false; fce.HasStyleInvalidated = false; fce.AncestorChangeInProgress = true; fce.UpdateStyleProperty(); fce.AncestorChangeInProgress = false; } } if (HasChildren(fe, fce)) { // Spin up a DescendentsWalker only when // the current node has children to walk // If there is another tree walk that has already visited the // current node then we do not need to re-walk its sub-tree. FrameworkContextData fcdata = FrameworkContextData.From(d.Dispatcher); if (!fcdata.WasNodeVisited(d, TreeChangeDelegate)) { // The TreeChangeInfo object is used here to track // information that we have because we're doing a tree walk. TreeChangeInfo parentInfo = new TreeChangeInfo(d, parent, isAddOperation); // PrePostDescendentsWalker is used instead of the standard // DescendentsWalker because we need a "post" callback to know when // to pop the parent's InheritableProperties cache from the stack. PrePostDescendentsWalker<TreeChangeInfo> walker = new PrePostDescendentsWalker<TreeChangeInfo>( TreeWalkPriority.LogicalTree, TreeChangeDelegate, TreeChangePostDelegate, parentInfo); fcdata.AddWalker(TreeChangeDelegate, walker); try { walker.StartWalk(d); } finally { fcdata.RemoveWalker(TreeChangeDelegate, walker); } } } else { // Degenerate case when the current node is a leaf node and has no children. TreeChangeInfo parentInfo = new TreeChangeInfo(d, parent, isAddOperation); // Degenerate case of OnAncestorChanged for a single node OnAncestorChanged(fe, fce, parentInfo); // Degenerate case of OnPostAncestorChanged for a single node OnPostAncestorChanged(d, parentInfo); } }
// Token: 0x06000C61 RID: 3169 RVA: 0x0002E1F8 File Offset: 0x0002C3F8 internal static void InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, bool isAddOperation) { FrameworkObject frameworkObject = new FrameworkObject(parent); if (!frameworkObject.IsValid) { parent = frameworkObject.FrameworkParent.DO; } FrameworkObject frameworkObject2 = new FrameworkObject(fe, fce); if (isAddOperation) { frameworkObject2.SetShouldLookupImplicitStyles(); } frameworkObject2.Reset(frameworkObject2.TemplatedParent); frameworkObject2.HasTemplateChanged = false; DependencyObject dependencyObject = (fe != null) ? fe : fce; if (fe != null) { if (fe.IsInitialized && !fe.HasLocalStyle) { fe.HasStyleChanged = false; fe.HasStyleInvalidated = false; fe.HasTemplateChanged = false; fe.AncestorChangeInProgress = true; fe.UpdateStyleProperty(); fe.AncestorChangeInProgress = false; } } else if (!fce.HasLocalStyle) { fce.HasStyleChanged = false; fce.HasStyleInvalidated = false; fce.AncestorChangeInProgress = true; fce.UpdateStyleProperty(); fce.AncestorChangeInProgress = false; } if (TreeWalkHelper.HasChildren(fe, fce)) { FrameworkContextData frameworkContextData = FrameworkContextData.From(dependencyObject.Dispatcher); if (frameworkContextData.WasNodeVisited(dependencyObject, TreeWalkHelper.TreeChangeDelegate)) { return; } TreeChangeInfo data = new TreeChangeInfo(dependencyObject, parent, isAddOperation); PrePostDescendentsWalker <TreeChangeInfo> prePostDescendentsWalker = new PrePostDescendentsWalker <TreeChangeInfo>(TreeWalkPriority.LogicalTree, TreeWalkHelper.TreeChangeDelegate, TreeWalkHelper.TreeChangePostDelegate, data); frameworkContextData.AddWalker(TreeWalkHelper.TreeChangeDelegate, prePostDescendentsWalker); try { prePostDescendentsWalker.StartWalk(dependencyObject); return; } finally { frameworkContextData.RemoveWalker(TreeWalkHelper.TreeChangeDelegate, prePostDescendentsWalker); } } TreeChangeInfo info = new TreeChangeInfo(dependencyObject, parent, isAddOperation); TreeWalkHelper.OnAncestorChanged(fe, fce, info); bool visitedViaVisualTree = false; TreeWalkHelper.OnPostAncestorChanged(dependencyObject, info, visitedViaVisualTree); }
// Token: 0x06000C65 RID: 3173 RVA: 0x0002E3C0 File Offset: 0x0002C5C0 internal static FrugalObjectList <DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo info, FrameworkElement fe, FrameworkContentElement fce, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent, bool wasSelfInheritanceParent) { DependencyObject dependencyObject = (fe != null) ? fe : fce; FrameworkObject frameworkObject = new FrameworkObject(fe, fce); FrugalObjectList <DependencyProperty> frugalObjectList = info.InheritablePropertiesStack.Peek(); int num = (frugalObjectList != null) ? frugalObjectList.Count : 0; FrugalObjectList <DependencyProperty> frugalObjectList2 = null; if (TreeWalkHelper.HasChildren(fe, fce)) { frugalObjectList2 = new FrugalObjectList <DependencyProperty>(num); } info.ResetInheritableValueIndexer(); for (int i = 0; i < num; i++) { DependencyProperty dependencyProperty = frugalObjectList[i]; PropertyMetadata metadata = dependencyProperty.GetMetadata(dependencyObject); if (metadata.IsInherited) { FrameworkPropertyMetadata frameworkPropertyMetadata = (FrameworkPropertyMetadata)metadata; bool flag = TreeWalkHelper.InvalidateTreeDependentProperty(info, dependencyObject, ref frameworkObject, dependencyProperty, frameworkPropertyMetadata, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent, wasSelfInheritanceParent); if (flag && frugalObjectList2 != null && (!TreeWalkHelper.SkipNow(frameworkObject.InheritanceBehavior) || frameworkPropertyMetadata.OverridesInheritanceBehavior)) { frugalObjectList2.Add(dependencyProperty); } } } return(frugalObjectList2); }
internal void OnAncestorChangedInternal(TreeChangeInfo parentTreeState) { bool inheritanceParent = this.IsSelfInheritanceParent; if (parentTreeState.Root != this) { this.HasStyleChanged = false; this.HasStyleInvalidated = false; this.HasTemplateChanged = false; } if (parentTreeState.IsAddOperation) new FrameworkObject(this, (FrameworkContentElement) null).SetShouldLookupImplicitStyles(); if (this.HasResourceReference) TreeWalkHelper.OnResourcesChanged((DependencyObject) this, ResourcesChangeInfo.TreeChangeInfo, false); FrugalObjectList<DependencyProperty> frugalObjectList = this.InvalidateTreeDependentProperties(parentTreeState, inheritanceParent); parentTreeState.InheritablePropertiesStack.Push(frugalObjectList); this.OnAncestorChanged(); if (!this.PotentiallyHasMentees) return; this.RaiseClrEvent(FrameworkElement.ResourcesChangedKey, EventArgs.Empty); }
internal FrugalObjectList<DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, bool isSelfInheritanceParent) { this.AncestorChangeInProgress = true; this.InVisibilityCollapsedTree = false; if (parentTreeState.TopmostCollapsedParentNode == null) { if (this.Visibility == Visibility.Collapsed) { parentTreeState.TopmostCollapsedParentNode = (object) this; this.InVisibilityCollapsedTree = true; } } else this.InVisibilityCollapsedTree = true; try { if (this.IsInitialized && !this.HasLocalStyle && this != parentTreeState.Root) this.UpdateStyleProperty(); ChildRecord childRecord = new ChildRecord(); bool isChildRecordValid = false; Style style = this.Style; Style themeStyle = this.ThemeStyle; DependencyObject templatedParent = this.TemplatedParent; int templateChildIndex = this.TemplateChildIndex; bool hasStyleChanged = this.HasStyleChanged; FrameworkElement.GetTemplatedParentChildRecord(templatedParent, templateChildIndex, out childRecord, out isChildRecordValid); FrameworkElement feParent; FrameworkContentElement fceParent; bool frameworkParent = FrameworkElement.GetFrameworkParent(this, out feParent, out fceParent); DependencyObject parent = (DependencyObject) null; InheritanceBehavior inheritanceBehavior = InheritanceBehavior.Default; if (frameworkParent) { if (feParent != null) { parent = (DependencyObject) feParent; inheritanceBehavior = feParent.InheritanceBehavior; } else { parent = (DependencyObject) fceParent; inheritanceBehavior = fceParent.InheritanceBehavior; } } if (!TreeWalkHelper.SkipNext(this.InheritanceBehavior) && !TreeWalkHelper.SkipNow(inheritanceBehavior)) this.SynchronizeInheritanceParent(parent); else if (!this.IsSelfInheritanceParent) this.SetIsSelfInheritanceParent(); return TreeWalkHelper.InvalidateTreeDependentProperties(parentTreeState, this, (FrameworkContentElement) null, style, themeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent); } finally { this.AncestorChangeInProgress = false; this.InVisibilityCollapsedTree = false; } }
// Invalidate all the properties that may have changed as a result of // changing this element's parent in the logical (and sometimes visual tree.) internal FrugalObjectList<DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, bool isSelfInheritanceParent) { AncestorChangeInProgress = true; try { // Style property is a special case of a non-inherited property that needs // invalidation for parent changes. Invalidate StyleProperty if it hasn't been // locally set because local value takes precedence over implicit references if (!HasLocalStyle && (this != parentTreeState.Root)) { UpdateStyleProperty(); } Style selfStyle = null; Style selfThemeStyle = null; DependencyObject templatedParent = null; int childIndex = -1; ChildRecord childRecord = new ChildRecord(); bool isChildRecordValid = false; selfStyle = Style; selfThemeStyle = ThemeStyle; templatedParent = TemplatedParent; childIndex = TemplateChildIndex; // StyleProperty could have changed during invalidation of ResourceReferenceExpressions if it // were locally set or during the invalidation of unresolved implicitly referenced style bool hasStyleChanged = HasStyleChanged; // Fetch selfStyle, hasStyleChanged and childIndex for the current node FrameworkElement.GetTemplatedParentChildRecord(templatedParent, childIndex, out childRecord, out isChildRecordValid); FrameworkElement parentFE; FrameworkContentElement parentFCE; bool hasParent = FrameworkElement.GetFrameworkParent(this, out parentFE, out parentFCE); DependencyObject parent = null; InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (hasParent) { if (parentFE != null) { parent = parentFE; parentInheritanceBehavior = parentFE.InheritanceBehavior; } else { parent = parentFCE; parentInheritanceBehavior = parentFCE.InheritanceBehavior; } } if (!TreeWalkHelper.SkipNext(InheritanceBehavior) && !TreeWalkHelper.SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent this.SynchronizeInheritanceParent(parent); } else if (!IsSelfInheritanceParent) { // Set IsSelfInheritanceParet on the root node at a tree boundary // so that all inheritable properties are cached on it. SetIsSelfInheritanceParent(); } // Loop through all cached inheritable properties for the parent to see if they should be invalidated. return TreeWalkHelper.InvalidateTreeDependentProperties(parentTreeState, /* fe = */ null, /* fce = */ this, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent); } finally { AncestorChangeInProgress = false; } }
/// <summary> /// Invalidate all the properties in the given /// collection of inheritable properties /// </summary> /// <remarks> /// This method is called during an [FE/FCE].OnAncestorChange /// </remarks> internal static FrugalObjectList<DependencyProperty> InvalidateTreeDependentProperties( TreeChangeInfo info, FrameworkElement fe, FrameworkContentElement fce, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent) { Debug.Assert(fe != null || fce != null, "Must have non-null current node"); DependencyObject d = fe != null ? (DependencyObject)fe : (DependencyObject)fce; FrameworkObject fo = new FrameworkObject(fe, fce); // Pull up the parent's InheritableProperties cache FrugalObjectList<DependencyProperty> parentInheritableProperties = info.InheritablePropertiesStack.Peek(); // Loop through all cached inheritable // to see if they should be invalidated. int inheritablePropertiesCount = parentInheritableProperties != null ? parentInheritableProperties.Count : 0; FrugalObjectList<DependencyProperty> currentInheritableProperties = null; if (HasChildren(fe, fce)) { currentInheritableProperties = new FrugalObjectList<DependencyProperty>(inheritablePropertiesCount); } info.ResetInheritableValueIndexer(); for (int i = 0; i < inheritablePropertiesCount; i++) { DependencyProperty inheritableProperty = parentInheritableProperties[i]; Debug.Assert(inheritableProperty.IsPotentiallyInherited, "if we got here, it means that this property is inheritable by someone"); PropertyMetadata metadata = inheritableProperty.GetMetadata(d); // Invalidate only properties that are marked as inheritable. // These are the ones that will be affected by an ancestor changes. if (metadata.IsInherited) { FrameworkPropertyMetadata fMetadata = (FrameworkPropertyMetadata)metadata; bool changed = InvalidateTreeDependentProperty(info, d, ref fo, inheritableProperty, fMetadata, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent); // If a change is detected then add the inheritable property to // the current list so that it can be used to invalidate further children if (changed && currentInheritableProperties != null) { Debug.Assert(!currentInheritableProperties.Contains(inheritableProperty), "InheritableProperties list should not have duplicates"); // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!SkipNow(fo.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { currentInheritableProperties.Add(inheritableProperty); } } } } return currentInheritableProperties; }
/// <summary> /// Invalidate this property if /// - It is not locally set and /// - It is not acquired from a style/template /// </summary> private static bool InvalidateTreeDependentProperty( TreeChangeInfo info, DependencyObject d, ref FrameworkObject fo, DependencyProperty dp, FrameworkPropertyMetadata fMetadata, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent) { Debug.Assert(d != null, "Must have non-null current node"); // This must be an inherited dependency property Debug.Assert(fMetadata.IsInherited == true, "This must be an inherited dependency property"); // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!SkipNext(fo.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { InheritablePropertyChangeInfo rootInfo = info.GetRootInheritableValue(dp); EffectiveValueEntry oldEntry = rootInfo.OldEntry; EffectiveValueEntry newEntry = info.IsAddOperation ? rootInfo.NewEntry : new EffectiveValueEntry(dp, BaseValueSourceInternal.Inherited); bool isForceInheritedProperty = IsForceInheritedProperty(dp); if (d != info.Root) { if (isSelfInheritanceParent) { oldEntry = d.GetValueEntry( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); } else { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } OperationType operationType = info.IsAddOperation ? OperationType.AddChild : OperationType.RemoveChild; if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { // If the oldValueSource is of lower precedence than Inheritance // only then do we need to Invalidate the property. Examples of // values with higher precedence are those that are locally set // or set via a style/template. return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, operationType) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else if (isForceInheritedProperty) { // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); // Re-coerce a force inherited property because it's coersion depends on treeness return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, operationType) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } } return false; }
private static void OnAncestorChanged(FrameworkElement fe, FrameworkContentElement fce, TreeChangeInfo info) { if (fe != null) { fe.OnAncestorChangedInternal(info); return; } fce.OnAncestorChangedInternal(info); }
// Invalidate all the properties that may have changed as a result of // changing this element's parent in the logical (and sometimes visual tree.) internal FrugalObjectList <DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, bool isSelfInheritanceParent, bool wasSelfInheritanceParent) { AncestorChangeInProgress = true; InVisibilityCollapsedTree = false; // False == we don't know whether we're in a visibility collapsed tree. if (parentTreeState.TopmostCollapsedParentNode == null) { // There is no ancestor node with Visibility=Collapsed. // See if "fe" is the root of a collapsed subtree. if (Visibility == Visibility.Collapsed) { // This is indeed the root of a collapsed subtree. // remember this information as we proceed on the tree walk. parentTreeState.TopmostCollapsedParentNode = this; // Yes, this FE node is in a visibility collapsed subtree. InVisibilityCollapsedTree = true; } } else { // There is an ancestor node somewhere above us with // Visibility=Collapsed. We're in a visibility collapsed subtree. InVisibilityCollapsedTree = true; } try { // Style property is a special case of a non-inherited property that needs // invalidation for parent changes. Invalidate StyleProperty if it hasn't been // locally set because local value takes precedence over implicit references if (IsInitialized && !HasLocalStyle && (this != parentTreeState.Root)) { UpdateStyleProperty(); } Style selfStyle = null; Style selfThemeStyle = null; DependencyObject templatedParent = null; int childIndex = -1; ChildRecord childRecord = new ChildRecord(); bool isChildRecordValid = false; selfStyle = Style; selfThemeStyle = ThemeStyle; templatedParent = TemplatedParent; childIndex = TemplateChildIndex; // StyleProperty could have changed during invalidation of ResourceReferenceExpressions if it // were locally set or during the invalidation of unresolved implicitly referenced style bool hasStyleChanged = HasStyleChanged; // Fetch selfStyle, hasStyleChanged and childIndex for the current node FrameworkElement.GetTemplatedParentChildRecord(templatedParent, childIndex, out childRecord, out isChildRecordValid); FrameworkElement parentFE; FrameworkContentElement parentFCE; bool hasParent = FrameworkElement.GetFrameworkParent(this, out parentFE, out parentFCE); DependencyObject parent = null; InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (hasParent) { if (parentFE != null) { parent = parentFE; parentInheritanceBehavior = parentFE.InheritanceBehavior; } else { parent = parentFCE; parentInheritanceBehavior = parentFCE.InheritanceBehavior; } } if (!TreeWalkHelper.SkipNext(InheritanceBehavior) && !TreeWalkHelper.SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent this.SynchronizeInheritanceParent(parent); } else if (!IsSelfInheritanceParent) { // Set IsSelfInheritanceParet on the root node at a tree boundary // so that all inheritable properties are cached on it. SetIsSelfInheritanceParent(); } // Loop through all cached inheritable properties for the parent to see if they should be invalidated. return(TreeWalkHelper.InvalidateTreeDependentProperties(parentTreeState, /* fe = */ this, /* fce = */ null, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent, wasSelfInheritanceParent)); } finally { AncestorChangeInProgress = false; InVisibilityCollapsedTree = false; // 'false' just means 'we don't know' - see comment at definition of the flag. } }
// Invalidate all the properties that may have changed as a result of // changing this element's parent in the logical (and sometimes visual tree.) internal FrugalObjectList<DependencyProperty> InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, bool isSelfInheritanceParent) { AncestorChangeInProgress = true; InVisibilityCollapsedTree = false; // False == we don't know whether we're in a visibility collapsed tree. if (parentTreeState.TopmostCollapsedParentNode == null) { // There is no ancestor node with Visibility=Collapsed. // See if "fe" is the root of a collapsed subtree. if (Visibility == Visibility.Collapsed) { // This is indeed the root of a collapsed subtree. // remember this information as we proceed on the tree walk. parentTreeState.TopmostCollapsedParentNode = this; // Yes, this FE node is in a visibility collapsed subtree. InVisibilityCollapsedTree = true; } } else { // There is an ancestor node somewhere above us with // Visibility=Collapsed. We're in a visibility collapsed subtree. InVisibilityCollapsedTree = true; } try { // Style property is a special case of a non-inherited property that needs // invalidation for parent changes. Invalidate StyleProperty if it hasn't been // locally set because local value takes precedence over implicit references if (IsInitialized && !HasLocalStyle && (this != parentTreeState.Root)) { UpdateStyleProperty(); } Style selfStyle = null; Style selfThemeStyle = null; DependencyObject templatedParent = null; int childIndex = -1; ChildRecord childRecord = new ChildRecord(); bool isChildRecordValid = false; selfStyle = Style; selfThemeStyle = ThemeStyle; templatedParent = TemplatedParent; childIndex = TemplateChildIndex; // StyleProperty could have changed during invalidation of ResourceReferenceExpressions if it // were locally set or during the invalidation of unresolved implicitly referenced style bool hasStyleChanged = HasStyleChanged; // Fetch selfStyle, hasStyleChanged and childIndex for the current node FrameworkElement.GetTemplatedParentChildRecord(templatedParent, childIndex, out childRecord, out isChildRecordValid); FrameworkElement parentFE; FrameworkContentElement parentFCE; bool hasParent = FrameworkElement.GetFrameworkParent(this, out parentFE, out parentFCE); DependencyObject parent = null; InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (hasParent) { if (parentFE != null) { parent = parentFE; parentInheritanceBehavior = parentFE.InheritanceBehavior; } else { parent = parentFCE; parentInheritanceBehavior = parentFCE.InheritanceBehavior; } } if (!TreeWalkHelper.SkipNext(InheritanceBehavior) && !TreeWalkHelper.SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent this.SynchronizeInheritanceParent(parent); } else if (!IsSelfInheritanceParent) { // Set IsSelfInheritanceParet on the root node at a tree boundary // so that all inheritable properties are cached on it. SetIsSelfInheritanceParent(); } // Loop through all cached inheritable properties for the parent to see if they should be invalidated. return TreeWalkHelper.InvalidateTreeDependentProperties(parentTreeState, /* fe = */ this, /* fce = */ null, selfStyle, selfThemeStyle, ref childRecord, isChildRecordValid, hasStyleChanged, isSelfInheritanceParent); } finally { AncestorChangeInProgress = false; InVisibilityCollapsedTree = false; // 'false' just means 'we don't know' - see comment at definition of the flag. } }