// Token: 0x060064AD RID: 25773 RVA: 0x001C3DF0 File Offset: 0x001C1FF0 internal void SetShouldLookupImplicitStyles() { if (!this.ShouldLookupImplicitStyles) { FrameworkObject frameworkParent = this.FrameworkParent; if (frameworkParent.IsValid && frameworkParent.ShouldLookupImplicitStyles) { this.ShouldLookupImplicitStyles = true; } } }
// Set the ShouldLookupImplicitStyles flag on the current // node if the parent has it set to true. internal void SetShouldLookupImplicitStyles() { if (!ShouldLookupImplicitStyles) { FrameworkObject parent = FrameworkParent; if (parent.IsValid && parent.ShouldLookupImplicitStyles) { ShouldLookupImplicitStyles = true; } } }
// Token: 0x0600647E RID: 25726 RVA: 0x001C3364 File Offset: 0x001C1564 internal FrameworkObject(DependencyObject d, bool throwIfNeither) { this = new FrameworkObject(d); if (throwIfNeither && this._fe == null && this._fce == null) { object obj = (d != null) ? d.GetType() : "NULL"; throw new InvalidOperationException(SR.Get("MustBeFrameworkDerived", new object[] { obj })); } }
// Token: 0x060064A1 RID: 25761 RVA: 0x001C3AA4 File Offset: 0x001C1CA4 internal static bool IsEffectiveAncestor(DependencyObject d1, DependencyObject d2) { FrameworkObject frameworkObject = new FrameworkObject(d2); while (frameworkObject.DO != null) { if (frameworkObject.DO == d1) { return(true); } frameworkObject.Reset(frameworkObject.EffectiveParent); } return(false); }
// Token: 0x060064A6 RID: 25766 RVA: 0x001C3B9C File Offset: 0x001C1D9C internal FrameworkObject GetPreferVisualParent(bool force) { InheritanceBehavior inheritanceBehavior = force ? InheritanceBehavior.Default : this.InheritanceBehavior; if (inheritanceBehavior != InheritanceBehavior.Default) { return(new FrameworkObject(null)); } FrameworkObject rawPreferVisualParent = this.GetRawPreferVisualParent(); switch (rawPreferVisualParent.InheritanceBehavior) { case InheritanceBehavior.SkipToAppNow: case InheritanceBehavior.SkipToThemeNow: case InheritanceBehavior.SkipAllNow: rawPreferVisualParent.Reset(null); break; } return(rawPreferVisualParent); }
/// <summary> /// Notification that the ResourceReferenceExpression has been set as a property's value /// </summary> /// <param name="d">DependencyObject being set</param> /// <param name="dp">Property being set</param> internal override void OnAttach(DependencyObject d, DependencyProperty dp) { _targetObject = d; _targetProperty = dp; FrameworkObject fo = new FrameworkObject(_targetObject); fo.HasResourceReference = true; if (!fo.IsValid) { // Listen for the InheritanceContextChanged event on the target node, // so that if this context hierarchy changes we can re-evaluate this expression. _targetObject.InheritanceContextChanged += new EventHandler(InvalidateExpressionValue); } }
// FindResourceInTree(fe/fce) Defaults: none internal static object FindResourceInTree( FrameworkElement feStart, FrameworkContentElement fceStart, DependencyProperty dp, object resourceKey, object unlinkedParent, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference, DependencyObject boundaryElement, out InheritanceBehavior inheritanceBehavior, out object source) { FrameworkObject startNode = new FrameworkObject(feStart, fceStart); FrameworkObject fo = startNode; object value; Style style; FrameworkTemplate frameworkTemplate; Style themeStyle; int loopCount = 0; bool hasParent = true; inheritanceBehavior = InheritanceBehavior.Default; while (hasParent) { Debug.Assert(startNode.IsValid || unlinkedParent != null, "Don't call FindResource with a null fe/fce and unlinkedParent"); if (loopCount > ContextLayoutManager.s_LayoutRecursionLimit) { // We suspect a loop here because the loop count // has exceeded the MAX_TREE_DEPTH expected throw new InvalidOperationException(SR.Get(SRID.LogicalTreeLoop)); } else { loopCount++; } // ------------------------------------------- // Lookup ResourceDictionary on the current instance // ------------------------------------------- style = null; frameworkTemplate = null; themeStyle = null; if (fo.IsFE) { FrameworkElement fe = fo.FE; value = fe.FindResourceOnSelf(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != DependencyProperty.UnsetValue) { source = fe; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceOnElement, source, resourceKey, value ); } return value; } if ((fe != startNode.FE) || StyleHelper.ShouldGetValueFromStyle(dp)) { style = fe.Style; } // Fetch the Template if ((fe != startNode.FE) || StyleHelper.ShouldGetValueFromTemplate(dp)) { frameworkTemplate = fe.TemplateInternal; } // Fetch the ThemeStyle if ((fe != startNode.FE) || StyleHelper.ShouldGetValueFromThemeStyle(dp)) { themeStyle = fe.ThemeStyle; } } else if (fo.IsFCE) { FrameworkContentElement fce = fo.FCE; value = fce.FindResourceOnSelf(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != DependencyProperty.UnsetValue) { source = fce; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceOnElement, source, resourceKey, value ); } return value; } if ((fce != startNode.FCE) || StyleHelper.ShouldGetValueFromStyle(dp)) { style = fce.Style; } // Fetch the ThemeStyle if ((fce != startNode.FCE) || StyleHelper.ShouldGetValueFromThemeStyle(dp)) { themeStyle = fce.ThemeStyle; } } if (style != null) { value = style.FindResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != DependencyProperty.UnsetValue) { source = style; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceInStyle, style.Resources, resourceKey, style, fo.DO, value ); } return value; } } if (frameworkTemplate != null) { value = frameworkTemplate.FindResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != DependencyProperty.UnsetValue) { source = frameworkTemplate; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceInTemplate, frameworkTemplate.Resources, resourceKey, frameworkTemplate, fo.DO, value ); } return value; } } if (themeStyle != null) { value = themeStyle.FindResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != DependencyProperty.UnsetValue) { source = themeStyle; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceInThemeStyle, themeStyle.Resources, resourceKey, themeStyle, fo.DO, value ); } return value; } } // If the current element that has been searched is the boundary element // then we need to progress no further if (boundaryElement != null && (fo.DO == boundaryElement)) { break; } // If the current element for resource lookup is marked such // then skip to the Application and/or System resources if (fo.IsValid && TreeWalkHelper.SkipNext(fo.InheritanceBehavior)) { inheritanceBehavior = fo.InheritanceBehavior; break; } // ------------------------------------------- // Find the next parent instance to lookup // ------------------------------------------- if (unlinkedParent != null) { // This is for the special case when the parser tries to fetch // a resource on an element even before it is hooked to the // tree. In this case the parser passes us the unlinkedParent // to use it for resource lookup. DependencyObject unlinkedParentAsDO = unlinkedParent as DependencyObject; if (unlinkedParentAsDO != null) { fo.Reset(unlinkedParentAsDO); if (fo.IsValid) { hasParent = true; } else { DependencyObject doParent = GetFrameworkParent(unlinkedParent); if (doParent != null) { fo.Reset(doParent); hasParent = true; } else { hasParent = false; } } } else { hasParent = false; } unlinkedParent = null; } else { Debug.Assert(fo.IsValid, "The current node being processed should be an FE/FCE"); fo = fo.FrameworkParent; hasParent = fo.IsValid; } // If the current element for resource lookup is marked such // then skip to the Application and/or System resources if (fo.IsValid && TreeWalkHelper.SkipNow(fo.InheritanceBehavior)) { inheritanceBehavior = fo.InheritanceBehavior; break; } } // No matching resource was found in the tree source = null; return DependencyProperty.UnsetValue; }
private bool ReceivePropertySet(object targetObject, XamlMember member, object value, DependencyObject templatedParent) { DependencyObject dependencyObject = targetObject as DependencyObject; DependencyProperty dependencyProperty; System.Windows.Baml2006.WpfXamlMember wpfMember = member as System.Windows.Baml2006.WpfXamlMember; if (wpfMember != null) { dependencyProperty = wpfMember.DependencyProperty; } else { // All DP backed XamlMembers must be wrapped by the WpfXamlMember. If it isn't wrapped, then it's not a DP return false; } //If we're not dealing with a DO or a DP, we cannot set an EffectiveValueEntry if (dependencyProperty == null || dependencyObject == null) { return false; } FrameworkObject fo = new FrameworkObject(dependencyObject); // If this isn't an FE that we're optimizing, defer to base. // // Similarly, if we don't have a templated parent, we're not optimizing, and defer to base // (This happens when FrameworkTemplate.LoadContent() is called.) if ((fo.TemplatedParent == null) || (templatedParent == null)) { return false; } // For template content, we skip the automatic BaseUriProperty and the UidProperty // (Implementation note: Doing this here because this is what we did with FEFs, // and because automation gets confused if the Uid isn't unique in the whole tree). if (dependencyProperty == System.Windows.Navigation.BaseUriHelper.BaseUriProperty) { // We only skip the automatic BaseUri property. If it's set explicitely, // that's passed through. if (!fo.IsInitialized) { return true; } } else if (dependencyProperty == UIElement.UidProperty) { return true; } Debug.Assert(fo.TemplatedParent == templatedParent); // Set the value onto the FE/FCE. HybridDictionary parentTemplateValues; if (!fo.StoresParentTemplateValues) { parentTemplateValues = new HybridDictionary(); StyleHelper.ParentTemplateValuesField.SetValue(dependencyObject, parentTemplateValues); fo.StoresParentTemplateValues = true; } else { parentTemplateValues = StyleHelper.ParentTemplateValuesField.GetValue(dependencyObject); } // Check if it is an expression Expression expr; int childIndex = fo.TemplateChildIndex; if ((expr = value as Expression) != null) { BindingExpressionBase bindingExpr; TemplateBindingExpression templateBindingExpr; if ((bindingExpr = expr as BindingExpressionBase) != null) { // If this is a BindingExpression then we need to store the corresponding // MarkupExtension into the per instance store for the unshared DP value. // Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, templatedParent, InstanceStyleData.InstanceValues); StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/); value = bindingExpr.ParentBindingBase; } else if ((templateBindingExpr = expr as TemplateBindingExpression) != null) { // If this is a TemplateBindingExpression then we create an equivalent Binding // MarkupExtension and store that in the per instance store for the unshared DP // value. We use Binding here because it has all the wiring in place to handle // change notifications through DependencySource and such. TemplateBindingExtension templateBindingExtension = templateBindingExpr.TemplateBindingExtension; // Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, templatedParent, InstanceStyleData.InstanceValues); StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/); // Create a Binding equivalent to the TemplateBindingExtension Binding binding = new Binding(); binding.Mode = BindingMode.OneWay; binding.RelativeSource = RelativeSource.TemplatedParent; binding.Path = new PropertyPath(templateBindingExtension.Property); binding.Converter = templateBindingExtension.Converter; binding.ConverterParameter = templateBindingExtension.ConverterParameter; value = binding; } else { Debug.Assert(false, "We do not have support for DynamicResource within unshared template content"); } } bool isMarkupExtension = value is MarkupExtension; // Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding/TemplateBinding. if (!dependencyProperty.IsValidValue(value)) { if (!isMarkupExtension && !(value is DeferredReference)) { throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dependencyProperty.Name)); } } parentTemplateValues[dependencyProperty] = value; dependencyObject.ProvideSelfAsInheritanceContext(value, dependencyProperty); EffectiveValueEntry entry = new EffectiveValueEntry(dependencyProperty); entry.BaseValueSourceInternal = BaseValueSourceInternal.ParentTemplate; entry.Value = value; if (isMarkupExtension) { // entry will be updated to hold the value StyleHelper.GetInstanceValue( StyleHelper.TemplateDataField, templatedParent, fo.FE, fo.FCE, childIndex, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, ref entry); } dependencyObject.UpdateEffectiveValue( dependencyObject.LookupEntry(dependencyProperty.GlobalIndex), dependencyProperty, dependencyProperty.GetMetadata(dependencyObject.DependencyObjectType), new EffectiveValueEntry() /* oldEntry */, ref entry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown); return true; }
/// <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); } }
internal static bool GetFrameworkParent(FrameworkContentElement current, out FrameworkElement feParent, out FrameworkContentElement fceParent) { FrameworkObject fo = new FrameworkObject(null, current); fo = fo.FrameworkParent; feParent = fo.FE; fceParent = fo.FCE; return fo.IsValid; }
/// <summary> /// Determine if the current DependencyObject is a candidate for /// producing inheritable values /// </summary> /// <remarks> /// This is called by both InvalidateTree and GetValueCore /// </remarks> internal static bool IsInheritanceNode( DependencyObject d, DependencyProperty dp, out InheritanceBehavior inheritanceBehavior) { // Assume can continue search inheritanceBehavior = InheritanceBehavior.Default; // Get Framework metadata (if exists) FrameworkPropertyMetadata metadata = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata; // Check for correct type of metadata if (metadata != null) { FrameworkObject fo = new FrameworkObject(d); if (fo.IsValid) { // If parent is a Framework type, then check if it is at a // tree separation boundary. Stop inheritance at the boundary unless // overridden by the medata.OverridesInheritanceBehavior flag. // GetValue from Parent only if instance is not a TreeSeparator // or fmetadata.OverridesInheritanceBehavior is set to override separated tree behavior if (fo.InheritanceBehavior != InheritanceBehavior.Default && !metadata.OverridesInheritanceBehavior) { // Hit a tree boundary inheritanceBehavior = fo.InheritanceBehavior; } } else { // If not a Framework type, then, this isn't an inheritance node. // Only Framework types know how to inherit return false; } // Check if metadata is marked as inheritable if (metadata.Inherits) { return true; } } // Not a framework type with inheritable metadata return 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; }
// // Add a child to a parent, using IAddChild. This has special support for Grid, // to allow backward compatibility with FEF-based templates that have Column/RowDefinition // children directly under the Grid. // private void AddNodeToParent( DependencyObject parent, FrameworkObject childFrameworkObject ) { Grid parentGrid; ColumnDefinition childNodeColumnDefinition; RowDefinition childNodeRowDefinition = null; if ( childFrameworkObject.IsFCE && (parentGrid = parent as Grid) != null && ( (childNodeColumnDefinition = childFrameworkObject.FCE as ColumnDefinition) != null || (childNodeRowDefinition = childFrameworkObject.FCE as RowDefinition) != null ) ) { if (childNodeColumnDefinition != null) { parentGrid.ColumnDefinitions.Add(childNodeColumnDefinition); } else if (childNodeRowDefinition != null) { parentGrid.RowDefinitions.Add(childNodeRowDefinition); } } else { // CALLBACK // Inheritable property invalidations will occur due to // OnParentChanged resulting from AddChild if (!(parent is IAddChild)) { throw new InvalidOperationException(SR.Get(SRID.TypeMustImplementIAddChild, parent.GetType().Name)); } ((IAddChild)parent).AddChild(childFrameworkObject.DO); } }
// This tree is used to instantiate a tree, represented by this factory. // It is instantiated as a normal tree without any template optimizations. // This is used by designers to inspect a template. internal FrameworkObject InstantiateUnoptimizedTree() { if (!_sealed) { throw new InvalidOperationException(SR.Get(SRID.FrameworkElementFactoryMustBeSealed)); } // Create the object. FrameworkObject frameworkObject = new FrameworkObject(CreateDependencyObject()); // Mark the beginning of initialization frameworkObject.BeginInit(); // Set values for this object, taking them from the shared values table. ProvideValueServiceProvider provideValueServiceProvider = null; FrameworkTemplate.SetTemplateParentValues( Name, frameworkObject.DO, _frameworkTemplate, ref provideValueServiceProvider ); // Get the first child FrameworkElementFactory childFactory = _firstChild; // If we have children, get this object's IAddChild, because it's going to be a parent. IAddChild iAddChild = null; if( childFactory != null ) { iAddChild = frameworkObject.DO as IAddChild; if (iAddChild == null) { throw new InvalidOperationException(SR.Get(SRID.TypeMustImplementIAddChild, frameworkObject.DO.GetType().Name)); } } // Build the children. while (childFactory != null) { if (childFactory._text != null) { iAddChild.AddText(childFactory._text); } else { // Use frameworkObject's IAddChild to add this node. FrameworkObject childFrameworkObject = childFactory.InstantiateUnoptimizedTree(); AddNodeToParent(frameworkObject.DO, childFrameworkObject ); } childFactory = childFactory._nextSibling; } // Mark the end of the initialization phase frameworkObject.EndInit(); return frameworkObject; }
// raise the SourceUpdatedEvent event (explicit polymorphism) internal static void OnSourceUpdated(DependencyObject d, DependencyProperty dp) { DataTransferEventArgs args = new DataTransferEventArgs(d, dp); args.RoutedEvent = Binding.SourceUpdatedEvent; FrameworkObject fo = new FrameworkObject(d); if (!fo.IsValid && d != null) { fo.Reset(Helper.FindMentor(d)); } fo.RaiseEvent(args); }
// Instantiate a tree. This is a recursive routine that will build the // subtree via calls to itself. The root node being instantiated will // have identical references for the "container" and "parent" parameters. // The "affectedChildren" and "noChildIndexChildren" parameters refer to the children // chain for the "container" object. This chain will have all the // children - not just the immediate children. The node being // instantiated here will be added to this chain. // The tree is instantiated in a depth-first traversal, so children nodes // are added to the chain in depth-first order as well. //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 internal DependencyObject InstantiateTree( UncommonField<HybridDictionary[]> dataField, DependencyObject container, DependencyObject parent, List<DependencyObject> affectedChildren, ref List<DependencyObject> noChildIndexChildren, ref FrugalStructList<ChildPropertyDependent> resourceDependents) { EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstBegin); FrameworkElement containerAsFE = container as FrameworkElement; bool isContainerAnFE = containerAsFE != null; DependencyObject treeNode = null; // If we have text, just add it to the parent. Otherwise create the child // subtree if (_text != null) { // of FrameworkContentElement parent. This is the logical equivalent // to what happens when adding a child to a visual collection. IAddChild addChildParent = parent as IAddChild; if (addChildParent == null) { throw new InvalidOperationException(SR.Get(SRID.TypeMustImplementIAddChild, parent.GetType().Name)); } else { addChildParent.AddText(_text); } } else { // Factory create instance treeNode = CreateDependencyObject(); EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstEnd); // The tree node is either a FrameworkElement or a FrameworkContentElement. // we'll deal with one or the other... FrameworkObject treeNodeFO = new FrameworkObject(treeNode); Visual3D treeNodeVisual3D = null; bool treeNodeIsVisual3D = false; if (!treeNodeFO.IsValid) { // If it's neither of those, we have special support for Visual3D treeNodeVisual3D = treeNode as Visual3D; if (treeNodeVisual3D != null) treeNodeIsVisual3D = true; } Debug.Assert( treeNodeFO.IsValid || (treeNodeVisual3D != null), "We should not be trying to instantiate a node that is neither FrameworkElement nor FrameworkContentElement. A type check should have been done when Type is set"); // And here's the bool we'll use to make the decision. bool treeNodeIsFE = treeNodeFO.IsFE; // Handle FE/FCE-specific optimizations if (!treeNodeIsVisual3D) { // Postpone "Initialized" event NewNodeBeginInit( treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE ); // Set the resource reference flags if (StyleHelper.HasResourceDependentsForChild(_childIndex, ref resourceDependents)) { treeNodeFO.HasResourceReference = true; } // Update the two chains that tracks all the nodes created // from all the FrameworkElementFactory of this Style. UpdateChildChains( _childName, _childIndex, treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE, affectedChildren, ref noChildIndexChildren ); // All FrameworkElementFactory-created elements point to the object // whose Style.VisualTree definition caused all this to occur NewNodeStyledParentProperty( container, isContainerAnFE, treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE ); // Initialize the per-instance data for the new element. This // needs to be done before any properties are invalidated. if (_childIndex != -1) { Debug.Assert( _frameworkTemplate != null ); StyleHelper.CreateInstanceDataForChild(dataField, container, treeNode, _childIndex, _frameworkTemplate.HasInstanceValues, ref _frameworkTemplate.ChildRecordFromChildIndex); } // If this element needs to know about the Loaded or Unloaded events, set the optimization // bit in the element if (HasLoadedChangeHandler) { BroadcastEventHelper.AddHasLoadedChangeHandlerFlagInAncestry(treeNode); } } else { if (_childName != null) { // Add this instance to the child index chain so that it may // be tracked by the style affectedChildren.Add(treeNode); } else { // Child nodes with no _childID (hence no _childIndex) are // tracked on a separate chain that will be appended to the // main chain for cleanup purposes. if (noChildIndexChildren == null) { noChildIndexChildren = new List<DependencyObject>(4); } noChildIndexChildren.Add(treeNode); } } // New node is initialized, build tree top down // (Node added before children of node) if (container == parent) { // Set the NameScope on the root of the Template generated tree TemplateNameScope templateNameScope = new TemplateNameScope(container); NameScope.SetNameScope(treeNode, templateNameScope); // This is the root of the tree if (isContainerAnFE) { // The root is added to the Visual tree (not logical) for the // case of FrameworkElement parents containerAsFE.TemplateChild = treeNodeFO.FE; } else { // The root is added to the logical tree for the case // of FrameworkContentElement parent. This is the logical equivalent // to what happens when adding a child to a visual collection. AddNodeToLogicalTree( (FrameworkContentElement)parent, _type, treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE ); } } else { // Call parent IAddChild to add treeNodeFO AddNodeToParent( parent, treeNodeFO ); } // Either set properties or invalidate them, depending on the type if (!treeNodeIsVisual3D) { // For non-3D content, we need to invalidate any properties that // came from FrameworkElementFactory.SetValue or VisulaTrigger.SetValue // so that they can get picked up. Debug.Assert( _frameworkTemplate != null ); StyleHelper.InvalidatePropertiesOnTemplateNode( container, treeNodeFO, _childIndex, ref _frameworkTemplate.ChildRecordFromChildIndex, false /*isDetach*/, this); } else { // For 3D, which doesn't understand templates, we set the properties directly // onto the newly-instantiated element. for (int i = 0; i < PropertyValues.Count; i++) { if (PropertyValues[i].ValueType == PropertyValueType.Set) { // Get the value out of the table. object o = PropertyValues[i].ValueInternal; // If it's a freezable that can't be frozen, it's probably not sharable, // so we make a copy of it. Freezable freezableValue = o as Freezable; if (freezableValue != null && !freezableValue.CanFreeze) { o = freezableValue.Clone(); } // Or, if it's a markup extension, get the value // to set on this property from the MarkupExtension itself. MarkupExtension me = o as MarkupExtension; if (me != null) { ProvideValueServiceProvider serviceProvider = new ProvideValueServiceProvider(); serviceProvider.SetData( treeNodeVisual3D, PropertyValues[i].Property ); o = me.ProvideValue( serviceProvider ); } // Finally, set the value onto the object. treeNodeVisual3D.SetValue(PropertyValues[i].Property, o); } else { // We don't support resource references, triggers, etc within the 3D content throw new NotSupportedException(SR.Get(SRID.Template3DValueOnly, PropertyValues[i].Property) ); } } } // Build child tree from factories FrameworkElementFactory childFactory = _firstChild; while (childFactory != null) { childFactory.InstantiateTree( dataField, container, treeNode, affectedChildren, ref noChildIndexChildren, ref resourceDependents); childFactory = childFactory._nextSibling; } if (!treeNodeIsVisual3D) { // Fire "Initialized" event NewNodeEndInit( treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE ); } } return treeNode; }
/// <summary> /// Find the element given name /// </summary> object INameScope.FindName(string name) { // _templatedParent is null if template.LoadContent() was responsible if (_templatedParent != null) { FrameworkObject fo = new FrameworkObject(_templatedParent); Debug.Assert(fo.IsFE); if (fo.IsFE) { return StyleHelper.FindNameInTemplateContent(fo.FE, name, fo.FE.TemplateInternal); } else { return null; } } else { if (_nameMap == null || name == null || name == String.Empty) return null; return _nameMap[name]; } }
// Given a FrameworkElement and a name string, this routine will try to find // a node with Name property set to the given name. It will search all // the child logical tree nodes of the given starting element. // If the name string is null or an empty string, the given starting element // is returned. // If the name is found on a FrameworkContentElement, an exception is thrown // If the name is not found attached to anything, an exception is thrown internal static FrameworkElement FindNamedFrameworkElement( FrameworkElement startElement, string targetName ) { FrameworkElement targetFE = null; if( targetName == null || targetName.Length == 0 ) { targetFE = startElement; } else { DependencyObject targetObject = null; targetObject = LogicalTreeHelper.FindLogicalNode( startElement, targetName ); if( targetObject == null ) { throw new ArgumentException( SR.Get(SRID.TargetNameNotFound, targetName)); } FrameworkObject fo = new FrameworkObject(targetObject); if( fo.IsFE ) { targetFE = fo.FE; } else { throw new InvalidOperationException(SR.Get(SRID.NamedObjectMustBeFrameworkElement, targetName)); } } return targetFE; }
// Fetchs the specified childRecord for the given template. Returns true if successful. internal static void GetTemplatedParentChildRecord( DependencyObject templatedParent, int childIndex, out ChildRecord childRecord, out bool isChildRecordValid) { FrameworkTemplate templatedParentTemplate = null; isChildRecordValid = false; childRecord = new ChildRecord(); // CS0177 if (templatedParent != null) { FrameworkObject foTemplatedParent = new FrameworkObject(templatedParent, true); Debug.Assert( foTemplatedParent.IsFE ); // This node is the result of a style expansion // Pick the owner for the VisualTree that generated this node templatedParentTemplate = foTemplatedParent.FE.TemplateInternal; Debug.Assert(templatedParentTemplate != null , "If this node is the result of a VisualTree expansion then it should have a parent template"); // Check if this Child Index is represented in FrameworkTemplate if (templatedParentTemplate != null && ((0 <= childIndex) && (childIndex < templatedParentTemplate.ChildRecordFromChildIndex.Count))) { childRecord = templatedParentTemplate.ChildRecordFromChildIndex[childIndex]; isChildRecordValid = true; } } }
internal static FrameworkObject GetContainingFrameworkElement(DependencyObject current) { FrameworkObject fo = new FrameworkObject(current); while (!fo.IsValid && fo.DO != null) { // The current object is neither a FrameworkElement nor a // FrameworkContentElement. We will now walk the "core" // tree looking for one. Visual visual; Visual3D visual3D; ContentElement ce; if ((visual = fo.DO as Visual) != null) { fo.Reset(VisualTreeHelper.GetParent(visual)); } else if ((ce = fo.DO as ContentElement) != null) { fo.Reset(ContentOperations.GetParent(ce)); } else if ((visual3D = fo.DO as Visual3D) != null) { fo.Reset(VisualTreeHelper.GetParent(visual3D)); } else { // The parent could be an application. fo.Reset(null); } } return fo; }
// Search the parent chain for a [Data|Table]Template in a ResourceDictionary. private static object FindTemplateResourceInTree(DependencyObject target, ArrayList keys, int exactMatch, ref int bestMatch) { Debug.Assert(target != null, "Don't call FindTemplateResource with a null target object"); ResourceDictionary table; object resource = null; FrameworkObject fo = new FrameworkObject(target); Debug.Assert(fo.IsValid, "Don't call FindTemplateResource with a target object that is neither a FrameworkElement nor a FrameworkContentElement"); while (fo.IsValid) { object candidate; // ------------------------------------------- // Lookup ResourceDictionary on the current instance // ------------------------------------------- // Fetch the ResourceDictionary // for the given target element table = GetInstanceResourceDictionary(fo.FE, fo.FCE); if( table != null ) { candidate = FindBestMatchInResourceDictionary( table, keys, exactMatch, ref bestMatch ); if (candidate != null) { resource = candidate; if (bestMatch < exactMatch) { // Exact match found, stop here. return resource; } } } // ------------------------------------------- // Lookup ResourceDictionary on the current instance's Style, if one exists. // ------------------------------------------- table = GetStyleResourceDictionary(fo.FE, fo.FCE); if( table != null ) { candidate = FindBestMatchInResourceDictionary( table, keys, exactMatch, ref bestMatch ); if (candidate != null) { resource = candidate; if (bestMatch < exactMatch) { // Exact match found, stop here. return resource; } } } // ------------------------------------------- // Lookup ResourceDictionary on the current instance's Theme Style, if one exists. // ------------------------------------------- table = GetThemeStyleResourceDictionary(fo.FE, fo.FCE); if( table != null ) { candidate = FindBestMatchInResourceDictionary( table, keys, exactMatch, ref bestMatch ); if (candidate != null) { resource = candidate; if (bestMatch < exactMatch) { // Exact match found, stop here. return resource; } } } // ------------------------------------------- // Lookup ResourceDictionary on the current instance's Template, if one exists. // ------------------------------------------- table = GetTemplateResourceDictionary(fo.FE, fo.FCE); if( table != null ) { candidate = FindBestMatchInResourceDictionary( table, keys, exactMatch, ref bestMatch ); if (candidate != null) { resource = candidate; if (bestMatch < exactMatch) { // Exact match found, stop here. return resource; } } } // If the current element for resource lookup is marked such then abort // lookup because resource lookup does not span tree boundaries if (fo.IsValid && TreeWalkHelper.SkipNext(fo.InheritanceBehavior)) { break; } // ------------------------------------------- // Find the next parent instance to lookup // ------------------------------------------- // Get Framework Parent fo = fo.FrameworkParent; // If the next parent for resource lookup is marked such then abort // lookup because resource lookup does not span tree boundaries if (fo.IsValid && TreeWalkHelper.SkipNext(fo.InheritanceBehavior)) { break; } } return resource; }
internal static bool IsEffectiveAncestor(DependencyObject d1, DependencyObject d2 #if TRACE_INHERITANCE_CONTEXT , DependencyProperty dp #endif ) { #if TRACE_INHERITANCE_CONTEXT int depth = 0; #endif for ( FrameworkObject fo = new FrameworkObject(d2); fo.DO != null; fo.Reset(fo.EffectiveParent)) { if (fo.DO == d1) { #if TRACE_INHERITANCE_CONTEXT Log("{0} creates cycle at depth {1}", LogIC(d2, dp, d1), depth); #endif return true; } #if TRACE_INHERITANCE_CONTEXT ++depth; #endif } return false; }
/// <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)); } } }
/// <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; }
/// <summary> /// </summary> internal static void InvalidateOnInheritablePropertyChange( FrameworkElement fe, FrameworkContentElement fce, InheritablePropertyChangeInfo info, bool skipStartNode) { DependencyProperty dp = info.Property; FrameworkObject fo = new FrameworkObject(fe, fce); Debug.Assert(fo.IsValid, "Node with the resources change notification must be an FE or an FCE."); if (HasChildren(fe, fce)) { // Spin up a DescendentsWalker only when // the current node has children to walk DependencyObject d = fo.DO; DescendentsWalker<InheritablePropertyChangeInfo> walker = new DescendentsWalker<InheritablePropertyChangeInfo>( TreeWalkPriority.LogicalTree, InheritablePropertyChangeDelegate, info); walker.StartWalk(d, skipStartNode); } else if (!skipStartNode) { // Degenerate case when the current node is a leaf node and has no children. // If the current node needs a notification, do so now. OnInheritablePropertyChanged(fo.DO, info); } }
/// <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; }
// raise the InheritedPropertyChanged event to mentees. Called from FE/FCE // OnPropertyChanged internal static void OnInheritedPropertyChanged(DependencyObject d, ref InheritablePropertyChangeInfo info, InheritanceBehavior inheritanceBehavior) { if (inheritanceBehavior == InheritanceBehavior.Default || IsForceInheritedProperty(info.Property)) { FrameworkObject fo = new FrameworkObject(d); fo.OnInheritedPropertyChanged(ref info); } }
/// <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); } }
// // Get the closest Framework type up the logical or physical tree // // (Shared between FrameworkElement and FrameworkContentElement) // internal static DependencyObject GetFrameworkParent(object current) { FrameworkObject fo = new FrameworkObject(current as DependencyObject); fo = fo.FrameworkParent; return fo.DO; }
/// <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 */); } } } } }
private DependencyObject FindAncestorOfType(Type type, int level, DependencyObject d, bool isTracing) { if (type == null) { if (TraceData.IsEnabled) TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorTypeNotSpecified); return null; } if (level < 1) { if (TraceData.IsEnabled) TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorLevelInvalid); return null; } // initialize search to start at the parent of the given DO FrameworkObject fo = new FrameworkObject(d); fo.Reset(fo.GetPreferVisualParent(true).DO); while (fo.DO != null) { if (isTracing) { TraceData.Trace(TraceEventType.Warning, TraceData.AncestorLookup( type.Name, TraceData.Identify(fo.DO))); } if (type.IsInstanceOfType(fo.DO)) // found it! { if (--level <= 0) break; } fo.Reset(fo.PreferVisualParent.DO); } return fo.DO; }
/// <summary> /// Callback on visiting each node in the descendency /// during an inheritable property change /// </summary> private static bool OnInheritablePropertyChanged( DependencyObject d, InheritablePropertyChangeInfo info) { Debug.Assert(d != null, "Must have non-null current node"); DependencyProperty dp = info.Property; EffectiveValueEntry oldEntry = info.OldEntry; EffectiveValueEntry newEntry = info.NewEntry; InheritanceBehavior inheritanceBehavior; bool inheritanceNode = IsInheritanceNode(d, dp, out inheritanceBehavior); bool isForceInheritedProperty = IsForceInheritedProperty(dp); // Note that if a node is marked SkipNext means it hasn't acquired any values from its parent and // hence we do not need to invalidate this node or any of its descendents. However if a node is // marked SkipNow then this node might have acquired values from its parent but none of its // descendents would. Hence in this case we process the current node but omit all of its descendents. if (inheritanceNode && (!SkipNext(inheritanceBehavior) || isForceInheritedProperty)) { PropertyMetadata metadata = dp.GetMetadata(d); EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex); // Found an inheritance node if (!d.IsSelfInheritanceParent) { DependencyObject parent = FrameworkElement.GetFrameworkParent(d); InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (parent != null) { FrameworkObject parentFO = new FrameworkObject(parent, true); parentInheritanceBehavior = parentFO.InheritanceBehavior; } if (!SkipNext(inheritanceBehavior) && !SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent d.SynchronizeInheritanceParent(parent); } // What should the oldValueSource on the child be? // When the oldValue on the parent was default it // means that the child also used its own default // and did not inherit from the parent. However // when the value on the parent was non-default // it means that the child inherited it. // Note that the oldValueSource on inheritablePropertyChangedData // is actually the parent's oldValueSource if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { // we use an empty EffectiveValueEntry as a signal that the old entry was the default value oldEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(d, dp)); } } else { oldEntry = d.GetValueEntry( entryIndex, dp, metadata, RequestFlags.RawEntry); } // If the oldValueSource is of lower precedence than Inheritance // only then do we need to Invalidate the property if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { // Since we do not hold a cache of the oldValue we need to supply one // in order to correctly fire the change notification return (d.UpdateEffectiveValue( entryIndex, dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (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, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (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 { return false; } } // Do not continue walk down subtree if the walk was forced to stop // (due to separated trees) return (inheritanceBehavior == InheritanceBehavior.Default || isForceInheritedProperty); }
private void InvalidatePropertiesOnTemplate(DependencyObject container, Object currentObject) { if (container != null) { DependencyObject dObject = currentObject as DependencyObject; if (dObject != null) { FrameworkObject child = new FrameworkObject(dObject); if (child.IsValid) { int templateChildIndex = child.TemplateChildIndex; // the template may have resource references for this child if (StyleHelper.HasResourceDependentsForChild(templateChildIndex, ref this.ResourceDependents)) { child.HasResourceReference = true; } // Invalidate properties on the element that come from the template. StyleHelper.InvalidatePropertiesOnTemplateNode(container, child, templateChildIndex, ref this.ChildRecordFromChildIndex, false, this.VisualTree); } } } }
// // This method // 1. Is called from AncestorChange InvalidateTree. // 2. It is used to create the InheritableProperties on the given node. // 3. It also accumulates oldValues for the inheritable properties that are about to be invalidated // internal FrugalObjectList<DependencyProperty> CreateParentInheritableProperties( DependencyObject d, DependencyObject parent, bool isAddOperation) { Debug.Assert(d != null, "Must have non-null current node"); if (parent == null) { return new FrugalObjectList<DependencyProperty>(0); } DependencyObjectType treeObjDOT = d.DependencyObjectType; // See if we have a cached value. EffectiveValueEntry[] parentEffectiveValues = null; uint parentEffectiveValuesCount = 0; uint inheritablePropertiesCount = 0; // If inheritable properties aren't cached on you then use the effective // values cache on the parent to discover those inherited properties that // may need to be invalidated on the children nodes. if (!parent.IsSelfInheritanceParent) { DependencyObject inheritanceParent = parent.InheritanceParent; if (inheritanceParent != null) { parentEffectiveValues = inheritanceParent.EffectiveValues; parentEffectiveValuesCount = inheritanceParent.EffectiveValuesCount; inheritablePropertiesCount = inheritanceParent.InheritableEffectiveValuesCount; } } else { parentEffectiveValues = parent.EffectiveValues; parentEffectiveValuesCount = parent.EffectiveValuesCount; inheritablePropertiesCount = parent.InheritableEffectiveValuesCount; } FrugalObjectList<DependencyProperty> inheritableProperties = new FrugalObjectList<DependencyProperty>((int) inheritablePropertiesCount); if (inheritablePropertiesCount == 0) { return inheritableProperties; } _rootInheritableValues = new InheritablePropertyChangeInfo[(int) inheritablePropertiesCount]; int inheritableIndex = 0; FrameworkObject foParent = new FrameworkObject(parent); for (uint i=0; i<parentEffectiveValuesCount; i++) { // Add all the inheritable properties from the effectiveValues // cache to the TreeStateCache on the parent EffectiveValueEntry entry = parentEffectiveValues[i]; DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[entry.PropertyIndex]; // There are UncommonFields also stored in the EffectiveValues cache. We need to exclude those. if ((dp != null) && dp.IsPotentiallyInherited) { PropertyMetadata metadata = dp.GetMetadata(parent.DependencyObjectType); if (metadata != null && metadata.IsInherited) { Debug.Assert(!inheritableProperties.Contains(dp), "EffectiveValues cache must not contains duplicate entries for the same DP"); FrameworkPropertyMetadata fMetadata = (FrameworkPropertyMetadata)metadata; // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!TreeWalkHelper.SkipNow(foParent.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { inheritableProperties.Add(dp); EffectiveValueEntry oldEntry; EffectiveValueEntry newEntry; oldEntry = d.GetValueEntry( d.LookupEntry(dp.GlobalIndex), dp, dp.GetMetadata(treeObjDOT), RequestFlags.DeferredReferences); if (isAddOperation) { // set up the new value newEntry = entry; if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default) || newEntry.HasModifiers) { newEntry = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else { newEntry = new EffectiveValueEntry(); } _rootInheritableValues[inheritableIndex++] = new InheritablePropertyChangeInfo(d, dp, oldEntry, newEntry); if (inheritablePropertiesCount == inheritableIndex) { // no more inheritable properties, bail early break; } } } } } return inheritableProperties; }
// FindResourceInternal(fe/fce) Defaults: none internal static object FindResourceInternal( FrameworkElement fe, FrameworkContentElement fce, DependencyProperty dp, object resourceKey, object unlinkedParent, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference, DependencyObject boundaryElement, bool isImplicitStyleLookup, out object source) { object value; InheritanceBehavior inheritanceBehavior = InheritanceBehavior.Default; if( TraceResourceDictionary.IsEnabled ) { FrameworkObject element = new FrameworkObject(fe, fce); TraceResourceDictionary.Trace( TraceEventType.Start, TraceResourceDictionary.FindResource, element.DO, resourceKey ); } try { // First try to find the resource in the tree if (fe != null || fce != null || unlinkedParent != null) { value = FindResourceInTree(fe, fce, dp, resourceKey, unlinkedParent, allowDeferredResourceReference, mustReturnDeferredResourceReference, boundaryElement, out inheritanceBehavior, out source); if (value != DependencyProperty.UnsetValue) { return value; } } // Then we try to find the resource in the App's Resources Application app = Application.Current; if (app != null && (inheritanceBehavior == InheritanceBehavior.Default || inheritanceBehavior == InheritanceBehavior.SkipToAppNow || inheritanceBehavior == InheritanceBehavior.SkipToAppNext)) { value = app.FindResourceInternal(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != null) { source = app; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceInApplication, resourceKey, value ); } return value; } } // Then we try to find the resource in the SystemResources but that is only if we aren't // doing an implicit style lookup. Implicit style lookup will stop at the app. if (!isImplicitStyleLookup && inheritanceBehavior != InheritanceBehavior.SkipAllNow && inheritanceBehavior != InheritanceBehavior.SkipAllNext) { value = SystemResources.FindResourceInternal(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference); if (value != null) { source = SystemResourceHost.Instance; if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.FoundResourceInTheme, source, resourceKey, value ); } return value; } } } finally { if( TraceResourceDictionary.IsEnabled ) { FrameworkObject element = new FrameworkObject(fe, fce); TraceResourceDictionary.Trace( TraceEventType.Stop, TraceResourceDictionary.FindResource, element.DO, resourceKey ); } } // We haven't found the resource. Trace a message to the debugger. // // Only trace if this isn't an implicit // style lookup and the element has been loaded if (TraceResourceDictionary.IsEnabledOverride && !isImplicitStyleLookup) { if ((fe != null && fe.IsLoaded) || (fce != null && fce.IsLoaded)) { TraceResourceDictionary.Trace( TraceEventType.Warning, TraceResourceDictionary.ResourceNotFound, resourceKey ); } else if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.ResourceNotFound, resourceKey ); } } source = null; return DependencyProperty.UnsetValue; }