// Token: 0x06000C6A RID: 3178 RVA: 0x0002E850 File Offset: 0x0002CA50 private static void InvalidateResourceReferences(DependencyObject d, ResourcesChangeInfo info) { LocalValueEnumerator localValueEnumerator = d.GetLocalValueEnumerator(); int count = localValueEnumerator.Count; if (count > 0) { ResourceReferenceExpression[] array = new ResourceReferenceExpression[count]; int num = 0; while (localValueEnumerator.MoveNext()) { LocalValueEntry localValueEntry = localValueEnumerator.Current; ResourceReferenceExpression resourceReferenceExpression = localValueEntry.Value as ResourceReferenceExpression; if (resourceReferenceExpression != null && info.Contains(resourceReferenceExpression.ResourceKey, false)) { array[num] = resourceReferenceExpression; num++; } } ResourcesChangedEventArgs e = new ResourcesChangedEventArgs(info); for (int i = 0; i < num; i++) { array[i].InvalidateExpressionValue(d, e); } } }
/// <summary> /// This event handler is called to invalidate the cached value held in /// this expression. This is called under the following 3 scenarios /// 1. InheritanceContext changes /// 2. Logical tree changes /// 3. ResourceDictionary changes /// </summary> internal void InvalidateExpressionValue(object sender, EventArgs e) { // VS has a scenario where a TreeWalk invalidates all reference expressions on a DependencyObject. // If there is a dependency between RRE's, // invalidating one RRE could cause _targetObject to be null on the other RRE. Hence this check. if (_targetObject == null) { return; } ResourcesChangedEventArgs args = e as ResourcesChangedEventArgs; if (args != null) { ResourcesChangeInfo info = args.Info; if (!info.IsTreeChange) { // This will happen when // 1. Theme changes // 2. Entire ResourceDictionary in the ancestry changes // 3. Single entry in a ResourceDictionary in the ancestry is changed // In all of the above cases it is sufficient to re-evaluate the cache // value alone. The mentor relation ships stay the same. InvalidateCacheValue(); } else { // This is the case of a logical tree change and hence we need to // re-evaluate both the mentor and the cached value. InvalidateMentorCache(); } } else { // There is no information provided by the EventArgs. Hence we // pessimistically invalidate both the mentor and the cached value. // This code path will execute when the InheritanceContext changes. InvalidateMentorCache(); } InvalidateTargetProperty(sender, e); }
/// <summary> /// Invalidates all the properties on the nodes in the given sub-tree /// that are referring to the resource[s] that are changing. /// </summary> internal static void InvalidateOnResourcesChange( FrameworkElement fe, FrameworkContentElement fce, ResourcesChangeInfo info) { Debug.Assert(fe != null || fce != null, "Node with the resources change notification must be an FE or an FCE."); // 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); fo.Reset(fo.TemplatedParent); fo.HasTemplateChanged = false; DependencyObject d = (fe != null) ? (DependencyObject)fe : (DependencyObject)fce; if (HasChildren(fe, fce)) { // Spin up a DescendentsWalker only when // the current node has children to walk DescendentsWalker<ResourcesChangeInfo> walker = new DescendentsWalker<ResourcesChangeInfo>( TreeWalkPriority.LogicalTree, ResourcesChangeDelegate, info); walker.StartWalk(d); } else { // Degenerate case when the current node is a leaf node and has no children. OnResourcesChanged(d, info, true); } }
internal ResourcesChangedEventArgs(ResourcesChangeInfo info) { _info = info; }
// Token: 0x06000C6B RID: 3179 RVA: 0x0002E8E0 File Offset: 0x0002CAE0 private static void InvalidateStyleAndReferences(DependencyObject d, ResourcesChangeInfo info, bool containsTypeOfKey) { FrameworkObject frameworkObject = new FrameworkObject(d); if (frameworkObject.IsFE) { FrameworkElement fe = frameworkObject.FE; if (containsTypeOfKey && !info.IsThemeChange && (fe.HasImplicitStyleFromResources || fe.Style == FrameworkElement.StyleProperty.GetMetadata(fe.DependencyObjectType).DefaultValue)) { fe.UpdateStyleProperty(); } if (fe.Style != null && fe.Style.HasResourceReferences && !fe.HasStyleChanged) { StyleHelper.InvalidateResourceDependents(d, info, ref fe.Style.ResourceDependents, false); } if (fe.TemplateInternal != null && fe.TemplateInternal.HasContainerResourceReferences) { StyleHelper.InvalidateResourceDependents(d, info, ref fe.TemplateInternal.ResourceDependents, false); } if (fe.TemplateChildIndex > 0) { FrameworkElement frameworkElement = (FrameworkElement)fe.TemplatedParent; FrameworkTemplate templateInternal = frameworkElement.TemplateInternal; if (!frameworkElement.HasTemplateChanged && templateInternal.HasChildResourceReferences) { StyleHelper.InvalidateResourceDependentsForChild(frameworkElement, fe, fe.TemplateChildIndex, info, templateInternal); } } if (!info.IsThemeChange) { Style themeStyle = fe.ThemeStyle; if (themeStyle != null && themeStyle.HasResourceReferences && themeStyle != fe.Style) { StyleHelper.InvalidateResourceDependents(d, info, ref themeStyle.ResourceDependents, false); return; } } } else if (frameworkObject.IsFCE) { FrameworkContentElement fce = frameworkObject.FCE; if (containsTypeOfKey && !info.IsThemeChange && (fce.HasImplicitStyleFromResources || fce.Style == FrameworkContentElement.StyleProperty.GetMetadata(fce.DependencyObjectType).DefaultValue)) { fce.UpdateStyleProperty(); } if (fce.Style != null && fce.Style.HasResourceReferences && !fce.HasStyleChanged) { StyleHelper.InvalidateResourceDependents(d, info, ref fce.Style.ResourceDependents, true); } if (fce.TemplateChildIndex > 0) { FrameworkElement frameworkElement2 = (FrameworkElement)fce.TemplatedParent; FrameworkTemplate templateInternal2 = frameworkElement2.TemplateInternal; if (!frameworkElement2.HasTemplateChanged && templateInternal2.HasChildResourceReferences) { StyleHelper.InvalidateResourceDependentsForChild(frameworkElement2, fce, fce.TemplateChildIndex, info, templateInternal2); } } if (!info.IsThemeChange) { Style themeStyle2 = fce.ThemeStyle; if (themeStyle2 != null && themeStyle2.HasResourceReferences && themeStyle2 != fce.Style) { StyleHelper.InvalidateResourceDependents(d, info, ref themeStyle2.ResourceDependents, false); } } } }
// Token: 0x06000C69 RID: 3177 RVA: 0x0002E674 File Offset: 0x0002C874 internal static void OnResourcesChanged(DependencyObject d, ResourcesChangeInfo info, bool raiseResourceChangedEvent) { bool flag = info.Contains(d.DependencyObjectType.SystemType, true); bool isThemeChange = info.IsThemeChange; bool isStyleResourcesChange = info.IsStyleResourcesChange; bool isTemplateResourcesChange = info.IsTemplateResourcesChange; bool flag2 = info.Container == d; FrameworkObject frameworkObject = new FrameworkObject(d); if (info.IsResourceAddOperation || info.IsCatastrophicDictionaryChange) { frameworkObject.SetShouldLookupImplicitStyles(); } if (frameworkObject.IsFE) { FrameworkElement fe = frameworkObject.FE; fe.HasStyleChanged = false; fe.HasStyleInvalidated = false; fe.HasTemplateChanged = false; if (info.IsImplicitDataTemplateChange) { ContentPresenter contentPresenter = fe as ContentPresenter; if (contentPresenter != null) { contentPresenter.ReevaluateTemplate(); } } if (fe.HasResourceReference) { TreeWalkHelper.InvalidateResourceReferences(fe, info); if ((!isStyleResourcesChange && !isTemplateResourcesChange) || !flag2) { TreeWalkHelper.InvalidateStyleAndReferences(d, info, flag); } } else if (flag && (fe.HasImplicitStyleFromResources || fe.Style == FrameworkElement.StyleProperty.GetMetadata(fe.DependencyObjectType).DefaultValue) && (!isStyleResourcesChange || !flag2)) { fe.UpdateStyleProperty(); } if (isThemeChange) { fe.UpdateThemeStyleProperty(); } if (raiseResourceChangedEvent && fe.PotentiallyHasMentees) { fe.RaiseClrEvent(FrameworkElement.ResourcesChangedKey, new ResourcesChangedEventArgs(info)); return; } } else { FrameworkContentElement fce = frameworkObject.FCE; fce.HasStyleChanged = false; fce.HasStyleInvalidated = false; if (fce.HasResourceReference) { TreeWalkHelper.InvalidateResourceReferences(fce, info); if ((!isStyleResourcesChange && !isTemplateResourcesChange) || !flag2) { TreeWalkHelper.InvalidateStyleAndReferences(d, info, flag); } } else if (flag && (fce.HasImplicitStyleFromResources || fce.Style == FrameworkContentElement.StyleProperty.GetMetadata(fce.DependencyObjectType).DefaultValue) && (!isStyleResourcesChange || !flag2)) { fce.UpdateStyleProperty(); } if (isThemeChange) { fce.UpdateThemeStyleProperty(); } if (raiseResourceChangedEvent && fce.PotentiallyHasMentees) { fce.RaiseClrEvent(FrameworkElement.ResourcesChangedKey, new ResourcesChangedEventArgs(info)); } } }
// // This method // 1. Invalidates all the resource references set on a template for a given child. // 2. Returns true if any were found // internal static void InvalidateResourceDependentsForChild( DependencyObject container, DependencyObject child, int childIndex, ResourcesChangeInfo info, FrameworkTemplate parentTemplate) { FrugalStructList<ChildPropertyDependent> resourceDependents = parentTemplate.ResourceDependents; int count = resourceDependents.Count; // Invalidate all properties on the given child that // are being driven via a resource reference in a template for (int i = 0; i < count; i++) { if (resourceDependents[i].ChildIndex == childIndex && info.Contains(resourceDependents[i].Name, false /*isImplicitStyleKey*/)) { DependencyProperty dp = resourceDependents[i].Property; // Update property on child child.InvalidateProperty(dp); // skip remaining dependents for the same property - we only // need to invalidate once. The list is sorted, so we just need // to skip until we find a new property. int dpIndex = dp.GlobalIndex; while (++i < resourceDependents.Count) { if (resourceDependents[i].ChildIndex != childIndex || resourceDependents[i].Property.GlobalIndex != dpIndex) { break; } } --i; // back up to let the for-loop do its normal increment } } }
/// <summary> /// Invalidates all properties that reference a resource. /// NOTE: The return value for this method indicates whether or not a ResourceReference /// property was found on the given object. This is to take care of the special case when /// programmatically changing a ResourceReference property value does not reflect on the /// bit stored on FrameworkElement or FrameworkContentElement that indicates whether /// the current instance has ResourceReference values set on it. This current operation /// is a point of synchronization for this flag. /// </summary> /// <remarks> /// This methods is called when one of the following operations occurred. /// 1) A tree change /// 2) A resource dictionary change /// 3) A modification to a single entry in a dictionary /// </remarks> private static void InvalidateResourceReferences( DependencyObject d, ResourcesChangeInfo info) { Debug.Assert(d != null, "Must have non-null current node"); // Find properties that have resource reference value LocalValueEnumerator localValues = d.GetLocalValueEnumerator(); int localValuesCount = localValues.Count; if (localValuesCount > 0) { // Resource reference invalidation involves two passes - first to // pick out what we need to invalidate, and the second to do the // actual invalidation. This is needed because LocalValueEnumerator // will halt if any local values have changed, which can happen // depending on what people are doing in their OnPropertyChanged // callback. // The following array is used to track the ResourceReferenceExpressions that we find ResourceReferenceExpression[] resources = new ResourceReferenceExpression[localValuesCount]; int invalidationCount = 0; // Pass #1 - find what needs invalidation while (localValues.MoveNext()) { // Is this a resource reference? ResourceReferenceExpression resource = localValues.Current.Value as ResourceReferenceExpression; if (resource != null) { // Record this property if it is referring // to a resource that is being changed if (info.Contains(resource.ResourceKey, false /*isImplicitStyleKey*/)) { resources[invalidationCount] = resource; invalidationCount++; } } } ResourcesChangedEventArgs args = new ResourcesChangedEventArgs(info); // Pass #2 - actually make the invalidation calls, now that we're // outside the LocalValueEnumerator. for (int i = 0; i < invalidationCount; i++) { // Let the resource reference throw away its cache // and invalidate the property in which it's held // re-evaluate expression resources[i].InvalidateExpressionValue(d, args); } } }
private void InvalidateResourceReferenceOnWindowCollection(WindowCollection wc, ResourcesChangeInfo info) { bool hasImplicitStyles = info.IsResourceAddOperation && HasImplicitStylesInResources; for (int i = 0; i < wc.Count; i++) { // calling thread is the same as the wc[i] thread so synchronously invalidate // resouces, else, post a dispatcher workitem to invalidate resources. if (wc[i].CheckAccess() == true) { // Set the ShouldLookupImplicitStyles flag on the App's windows // to true if App.Resources has implicit styles. if (hasImplicitStyles) wc[i].ShouldLookupImplicitStyles = true; TreeWalkHelper.InvalidateOnResourcesChange(wc[i], null, info); } else { wc[i].Dispatcher.BeginInvoke( DispatcherPriority.Send, (DispatcherOperationCallback) delegate(object obj) { object[] args = obj as object[]; // Set the ShouldLookupImplicitStyles flag on the App's windows // to true if App.Resources has implicit styles. if (hasImplicitStyles) ((FrameworkElement)args[0]).ShouldLookupImplicitStyles = true; TreeWalkHelper.InvalidateOnResourcesChange((FrameworkElement)args[0], null, (ResourcesChangeInfo)args[1]); return null; }, new object[] {wc[i], info} ); } } }
internal void InvalidateResourceReferences(ResourcesChangeInfo info) { // Invalidate ResourceReference properties on all the windows. // we Clone() the collection b/c if we don't then some other thread can be // modifying the collection while we iterate over it InvalidateResourceReferenceOnWindowCollection(WindowsInternal.Clone(), info); InvalidateResourceReferenceOnWindowCollection(NonAppWindowsInternal.Clone(), info); }
/// <summary> /// Called when the MergedDictionaries collection changes /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnMergedDictionariesChanged(object sender, NotifyCollectionChangedEventArgs e) { List<ResourceDictionary> oldDictionaries = null; List<ResourceDictionary> newDictionaries = null; ResourceDictionary mergedDictionary; ResourcesChangeInfo info; if (e.Action != NotifyCollectionChangedAction.Reset) { Invariant.Assert( (e.NewItems != null && e.NewItems.Count > 0) || (e.OldItems != null && e.OldItems.Count > 0), "The NotifyCollectionChanged event fired when no dictionaries were added or removed"); // If one or more resource dictionaries were removed we // need to remove the owners they were given by their // parent ResourceDictionary. if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) { oldDictionaries = new List<ResourceDictionary>(e.OldItems.Count); for (int i = 0; i < e.OldItems.Count; i++) { mergedDictionary = (ResourceDictionary)e.OldItems[i]; oldDictionaries.Add(mergedDictionary); RemoveParentOwners(mergedDictionary); } } // If one or more resource dictionaries were added to the merged // dictionaries collection we need to send down the parent // ResourceDictionary's owners. if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace) { newDictionaries = new List<ResourceDictionary>(e.NewItems.Count); for (int i = 0; i < e.NewItems.Count; i++) { mergedDictionary = (ResourceDictionary)e.NewItems[i]; newDictionaries.Add(mergedDictionary); // If the merged dictionary HasImplicitStyle mark the outer dictionary the same. if (!HasImplicitStyles && mergedDictionary.HasImplicitStyles) { HasImplicitStyles = true; } // If the parent dictionary is a theme dictionary mark the merged dictionary the same. if (IsThemeDictionary) { mergedDictionary.IsThemeDictionary = true; } PropagateParentOwners(mergedDictionary); } } info = new ResourcesChangeInfo(oldDictionaries, newDictionaries, false, false, null); } else { // Case when MergedDictionary collection is cleared info = ResourcesChangeInfo.CatastrophicDictionaryChangeInfo; } // Notify the owners of the change and fire // invalidation if already initialized NotifyOwners(info); }
// Call FrameworkElement.InvalidateTree with the right data private void NotifyOwners(ResourcesChangeInfo info) { bool shouldInvalidate = IsInitialized; bool hasImplicitStyles = info.IsResourceAddOperation && HasImplicitStyles; if (shouldInvalidate || hasImplicitStyles) { // Invalidate all FE owners if (_ownerFEs != null) { foreach (Object o in _ownerFEs) { FrameworkElement fe = o as FrameworkElement; if (fe != null) { // Set the HasImplicitStyles flag on the owner if (hasImplicitStyles) fe.ShouldLookupImplicitStyles = true; // If this dictionary has been initialized fire an invalidation // to let the tree know of this change. if (shouldInvalidate) TreeWalkHelper.InvalidateOnResourcesChange(fe, null, info); } } } // Invalidate all FCE owners if (_ownerFCEs != null) { foreach (Object o in _ownerFCEs) { FrameworkContentElement fce = o as FrameworkContentElement; if (fce != null) { // Set the HasImplicitStyles flag on the owner if (hasImplicitStyles) fce.ShouldLookupImplicitStyles = true; // If this dictionary has been initialized fire an invalidation // to let the tree know of this change. if (shouldInvalidate) TreeWalkHelper.InvalidateOnResourcesChange(null, fce, info); } } } // Invalidate all App owners if (_ownerApps != null) { foreach (Object o in _ownerApps) { Application app = o as Application; if (app != null) { // Set the HasImplicitStyles flag on the owner if (hasImplicitStyles) app.HasImplicitStylesInResources = true; // If this dictionary has been initialized fire an invalidation // to let the tree know of this change. if (shouldInvalidate) app.InvalidateResourceReferences(info); } } } } }
/// <summary> /// Callback on visiting each node in the descendency /// during a resources change. /// </summary> private static bool OnResourcesChangedCallback( DependencyObject d, ResourcesChangeInfo info) { OnResourcesChanged(d, info, true); // Continue walk down subtree return true; }
// Token: 0x06000C67 RID: 3175 RVA: 0x0002E60C File Offset: 0x0002C80C internal static void InvalidateOnResourcesChange(FrameworkElement fe, FrameworkContentElement fce, ResourcesChangeInfo info) { FrameworkObject frameworkObject = new FrameworkObject(fe, fce); frameworkObject.Reset(frameworkObject.TemplatedParent); frameworkObject.HasTemplateChanged = false; DependencyObject dependencyObject = (fe != null) ? fe : fce; if (TreeWalkHelper.HasChildren(fe, fce)) { DescendentsWalker <ResourcesChangeInfo> descendentsWalker = new DescendentsWalker <ResourcesChangeInfo>(TreeWalkPriority.LogicalTree, TreeWalkHelper.ResourcesChangeDelegate, info); descendentsWalker.StartWalk(dependencyObject); return; } TreeWalkHelper.OnResourcesChanged(dependencyObject, info, true); }
/// <summary> /// Process a resource change for the given DependencyObject. /// Return true if the DO has resource references. /// </summary> internal static void OnResourcesChanged( DependencyObject d, ResourcesChangeInfo info, bool raiseResourceChangedEvent) { Debug.Assert(d != null, "Must have non-null current node"); bool containsTypeOfKey = info.Contains(d.DependencyObjectType.SystemType, true /*isImplicitStyleKey*/); bool isSystemResourcesChange = info.IsThemeChange; bool isStyleResourcesChange = info.IsStyleResourcesChange; bool isTemplateResourcesChange = info.IsTemplateResourcesChange; bool isContainer = (info.Container == d); FrameworkObject fo = new FrameworkObject(d); // If a resource dictionary changed above this node then we need to // synchronize the ShouldLookupImplicitStyles flag with respect to // our parent here. if (info.IsResourceAddOperation || info.IsCatastrophicDictionaryChange) { fo.SetShouldLookupImplicitStyles(); } // Invalidate implicit and explicit resource // references on current instance if (fo.IsFE) { // If this is a FrameworkElement FrameworkElement fe = fo.FE; fe.HasStyleChanged = false; // detect style changes that arise from work done here fe.HasStyleInvalidated = false; fe.HasTemplateChanged = false; // detect template changes that arise from work done here if (fe.HasResourceReference) { // Invalidate explicit ResourceReference properties on the current instance. // If the Style property comes from an implicit resource reference that // will be invalidated too. InvalidateResourceReferences(fe, info); // There is no need to invalidate the resources references on the // container object if this call is a result of a style/template // change. This is because the style/template change would have // already invalidated all the container dependents and all the // resources references on the container would have been a part of it. if ((!isStyleResourcesChange && !isTemplateResourcesChange ) || !isContainer) { InvalidateStyleAndReferences(d, info, containsTypeOfKey); } } else if (containsTypeOfKey && (fe.HasImplicitStyleFromResources || fe.Style == FrameworkElement.StyleProperty.GetMetadata(fe.DependencyObjectType).DefaultValue)) { // If The Style property on the given instance has been // fetched by an implicit resource lookup then // it needs to be invalidated. Also we need to do this // invalidation only if the dictionary/resources that is // changing matches the implicit key used for the resource lookup. // The StyleProperty does not need to be invalidated if this // call is the result of a style change if (!isStyleResourcesChange || !isContainer) { fe.UpdateStyleProperty(); } } // If there has been a Theme change then // invalidate the ThemeStyleProperty if (isSystemResourcesChange) { fe.UpdateThemeStyleProperty(); } // Raise the ResourcesChanged Event so that ResourceReferenceExpressions // on non-[FE/FCE] (example Freezables) listening for this can then update // their values if (raiseResourceChangedEvent && fe.PotentiallyHasMentees) { fe.RaiseClrEvent(FrameworkElement.ResourcesChangedKey, new ResourcesChangedEventArgs(info)); } } else { // If this is a FrameworkContentElement FrameworkContentElement fce = fo.FCE; fce.HasStyleChanged = false; // detect style changes that arise from work done here fce.HasStyleInvalidated = false; if (fce.HasResourceReference) { // Invalidate explicit ResourceReference properties on the current instance. // If the Style property comes from an implicit resource reference that // will be invalidated too. InvalidateResourceReferences(fce, info); // There is no need to invalidate the resources references on the // container object if this call is a result of a style/template // change. This is because the style/template change would have // already invalidated all the container dependents and all the // resources references on the container would have been a part of it. if ((!isStyleResourcesChange && !isTemplateResourcesChange ) || !isContainer) { InvalidateStyleAndReferences(d, info, containsTypeOfKey); } } else if (containsTypeOfKey && (fce.HasImplicitStyleFromResources || fce.Style == FrameworkContentElement.StyleProperty.GetMetadata(fce.DependencyObjectType).DefaultValue)) { // If The Style property on the given instance has been // fetched by an implicit resource lookup then // it needs to be invalidated. Also we need to do this // invalidation only if the dictionary/resources that is // changing matches the implicit key used for the resource lookup. // The StyleProperty does not need to be invalidated if this // call is the result of a style change if (!isStyleResourcesChange || !isContainer) { fce.UpdateStyleProperty(); } } // If there has been a Theme change then // invalidate the ThemeStyleProperty if (isSystemResourcesChange) { fce.UpdateThemeStyleProperty(); } // Raise the ResourcesChanged Event so that ResourceReferenceExpressions // on non-[FE/FCE] (example Freezables) listening for this can then update // their values if (raiseResourceChangedEvent && fce.PotentiallyHasMentees) { fce.RaiseClrEvent(FrameworkElement.ResourcesChangedKey, new ResourcesChangedEventArgs(info)); } } }
// Token: 0x06000C68 RID: 3176 RVA: 0x0002E666 File Offset: 0x0002C866 private static bool OnResourcesChangedCallback(DependencyObject d, ResourcesChangeInfo info, bool visitedViaVisualTree) { TreeWalkHelper.OnResourcesChanged(d, info, true); return(true); }
/// <summary> /// Invalidates all properties that reference a resource and are set via a style/template. /// </summary> /// <remarks> /// This methods is called when one of the following operations occurred. /// 1) A resource dictionary change /// 2) A modification to a single entry in a dictionary /// </remarks> private static void InvalidateStyleAndReferences( DependencyObject d, ResourcesChangeInfo info, bool containsTypeOfKey) { Debug.Assert(d != null, "Must have non-null current node"); FrameworkObject fo = new FrameworkObject(d); if (fo.IsFE) { FrameworkElement fe = fo.FE; if (containsTypeOfKey && !info.IsThemeChange && (fe.HasImplicitStyleFromResources || fe.Style == FrameworkElement.StyleProperty.GetMetadata(fe.DependencyObjectType).DefaultValue)) { // If The Style property on the given instance has been // fetched by an implicit resource lookup then // it needs to be invalidated. Also we need to do this // invalidation only if the dictionary/resources that is // changing matches the implicit key used for the resource lookup. // If we invalidate the style then we do not need to // InvalidateResourceDependents because applying an // all new style will have the same effect fe.UpdateStyleProperty(); } else if (fe.Style != null && fe.Style.HasResourceReferences) { // Check for resource references contained within associated Style. // If found, invalidate all properties that are being driven by a resource. // If the style has changed recently, that change would have already // invalidated these properties. if (!fe.HasStyleChanged) { StyleHelper.InvalidateResourceDependents(d, info, ref fe.Style.ResourceDependents, false /* invalidateVisualTreeToo */); } } if (fe.TemplateInternal != null && fe.TemplateInternal.HasContainerResourceReferences) { // Check for resource references contained within associated Template. // If found, invalidate all properties that are being driven by a resource StyleHelper.InvalidateResourceDependents(d, info, ref fe.TemplateInternal.ResourceDependents, false /* invalidateVisualTreeToo */); } if (fe.TemplateChildIndex > 0) { // Check for resource references contained within parent's Template. // If found, invalidate all properties that are being driven by a resource FrameworkElement templatedParent = (FrameworkElement)fe.TemplatedParent; FrameworkTemplate parentTemplate = templatedParent.TemplateInternal; if (!templatedParent.HasTemplateChanged && parentTemplate.HasChildResourceReferences) { StyleHelper.InvalidateResourceDependentsForChild( templatedParent, fe, fe.TemplateChildIndex, info, parentTemplate); } } if (!info.IsThemeChange) { // Invalidate ResourceReferences on ThemeStyle only if this insn't a Theme change. // It it is then ThemeStyle would already have been invalidated and hence there isn't // a need to duplicate it here. Style themeStyle = fe.ThemeStyle; if (themeStyle != null && themeStyle.HasResourceReferences) { if (themeStyle != fe.Style) { StyleHelper.InvalidateResourceDependents(d, info, ref themeStyle.ResourceDependents, false /* invalidateVisualTreeToo */); } } } } else if (fo.IsFCE) { FrameworkContentElement fce = fo.FCE; if (containsTypeOfKey && !info.IsThemeChange && (fce.HasImplicitStyleFromResources || fce.Style == FrameworkContentElement.StyleProperty.GetMetadata(fce.DependencyObjectType).DefaultValue)) { // If The Style property on the given instance has been // fetched by an implicit resource lookup then // it needs to be invalidated. Also we need to do this // invalidation only if the dictionary/resources that is // changing matches the implicit key used for the resource lookup. // If we invalidate the style then we do not need to // InvalidateResourceDependents because applying an // all new style will have the same effect fce.UpdateStyleProperty(); } else if (fce.Style != null && fce.Style.HasResourceReferences) { // Check for resource references contained within associated Style. // If found, invalidate all properties that are being driven by a resource // If the style has changed recently, that change would have already // invalidated these properties. if (!fce.HasStyleChanged) { StyleHelper.InvalidateResourceDependents(d, info, ref fce.Style.ResourceDependents, ! false /*invalidateVisualTreeToo */); } } if (fce.TemplateChildIndex > 0) { // Check for resource references contained within parent's Template. // If found, invalidate all properties that are being driven by a resource FrameworkElement templatedParent = (FrameworkElement)fce.TemplatedParent; FrameworkTemplate parentTemplate = templatedParent.TemplateInternal; if (!templatedParent.HasTemplateChanged && parentTemplate.HasChildResourceReferences) { StyleHelper.InvalidateResourceDependentsForChild( templatedParent, fce, fce.TemplateChildIndex, info, parentTemplate); } } if (!info.IsThemeChange) { // Invalidate ResourceReferences on ThemeStyle only if this insn't a Theme change. // It it is then ThemeStyle would already have been invalidated and hence there isn't // a need to duplicate it here. Style themeStyle = fce.ThemeStyle; if (themeStyle != null && themeStyle.HasResourceReferences) { if (themeStyle != fce.Style) { StyleHelper.InvalidateResourceDependents(d, info, ref themeStyle.ResourceDependents, false /*invalidateVisualTreeToo */); } } } } }
// // This method // 1. Invalidates all the resource references set on a style or a template. // // Note: In the case that the visualtree was not generated from the particular // style in question we will skip past those resource references that haven't // been set on the container. This condition is described by the // invalidateVisualTreeToo flag being false. // internal static void InvalidateResourceDependents( DependencyObject container, ResourcesChangeInfo info, ref FrugalStructList<ChildPropertyDependent> resourceDependents, bool invalidateVisualTreeToo) { List<DependencyObject> styledChildren = TemplatedFeChildrenField.GetValue(container); // Invalidate all properties on this container and its children that // are being driven via a resource reference in a style for (int i = 0; i < resourceDependents.Count; i++) { // Invalidate property // 1. If nothing is known about the data or // 2. If the data tells us the key in the dictionary that was modified and this property is refering to it or // 3. If it tells us info about the changed dictionaries and this property was refering to one of their entries // 4. If this a theme change if (info.Contains(resourceDependents[i].Name, false /*isImplicitStyleKey*/)) { DependencyObject child = null; DependencyProperty invalidProperty = resourceDependents[i].Property; int childIndex = resourceDependents[i].ChildIndex; if (childIndex == 0) { // Index '0' means 'self' (container) child = container; } else if (invalidateVisualTreeToo) { Debug.Assert(styledChildren != null, "Should reach here only if the template tree has already been created"); // Locate child to invalidate child = GetChild(styledChildren, childIndex); if (child == null) { throw new InvalidOperationException(SR.Get(SRID.ChildTemplateInstanceDoesNotExist)); } } if (child != null) { // Invalidate property on child child.InvalidateProperty(invalidProperty); // skip remaining dependents for the same property - we only // need to invalidate once. The list is sorted, so we just need // to skip until we find a new property. int dpIndex = invalidProperty.GlobalIndex; while (++i < resourceDependents.Count) { if (resourceDependents[i].ChildIndex != childIndex || resourceDependents[i].Property.GlobalIndex != dpIndex) { break; } } --i; // back up to let the for-loop do its normal increment } } } }