// The ordering of how things are created and which methods are called are ABSOLUTELY critical // Getting this order slightly off will result in several issues that are very hard to debug. // // The order must be: // Register name to the TemplateNameScope (Either the real name specified by x:Name or // RuntimeNameProperty or a fake name that we have to generate to call // RegisterName. This is CRUCIAL since RegisterName sets the TemplatedParent // and the TemplateChildIndex on the object // If we're dealing with the root, wire the object to the parent (via FE.TemplateChild // if we're dealing with an FE as the container or using FEF if it's not an FE) // Invalidate properties on the object private DependencyObject LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List<DependencyObject> affectedChildren, UncommonField<Hashtable> templatedNonFeChildrenField) { if (Names == null) { Names = new XamlContextStack<Frame>(() => new Frame()); } DependencyObject rootObject = null; if (TraceMarkup.IsEnabled) { TraceMarkup.Trace(TraceEventType.Start, TraceMarkup.Load); } FrameworkElement feContainer = container as FrameworkElement; bool isTemplatedParentAnFE = feContainer != null; TemplateNameScope nameScope = new TemplateNameScope(container, affectedChildren, this); XamlObjectWriterSettings settings = System.Windows.Markup.XamlReader.CreateObjectWriterSettings(_templateHolder.ObjectWriterParentSettings); settings.ExternalNameScope = nameScope; settings.RegisterNamesOnExternalNamescope = true; IEnumerator<String> nameEnumerator = ChildNames.GetEnumerator(); // Delegate for AfterBeginInit event settings.AfterBeginInitHandler = delegate(object sender, System.Xaml.XamlObjectEventArgs args) { HandleAfterBeginInit(args.Instance, ref rootObject, container, feContainer, nameScope, nameEnumerator); if (XamlSourceInfoHelper.IsXamlSourceInfoEnabled) { XamlSourceInfoHelper.SetXamlSourceInfo(args.Instance, args, null); } }; // Delegate for BeforeProperties event settings.BeforePropertiesHandler = delegate(object sender, System.Xaml.XamlObjectEventArgs args) { HandleBeforeProperties(args.Instance, ref rootObject, container, feContainer, nameScope); }; // Delegate for XamlSetValue event settings.XamlSetValueHandler = delegate(object sender, System.Windows.Markup.XamlSetValueEventArgs setArgs) { setArgs.Handled = ReceivePropertySet(sender, setArgs.Member, setArgs.Value, container); }; XamlObjectWriter objectWriter = _templateHolder.ObjectWriterFactory.GetXamlObjectWriter(settings); try { LoadTemplateXaml(objectWriter); } finally { if (TraceMarkup.IsEnabled) { TraceMarkup.Trace(TraceEventType.Stop, TraceMarkup.Load, rootObject); } } return rootObject; }
// 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; }
private void HandleAfterBeginInit(object createdObject, ref DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, TemplateNameScope nameScope, IEnumerator<String> nameEnumerator) { // We need to wire names for all FEs and FCEs. We do this as soon as the object is // initalized since it needs to happen before we assign any properties or wire to the parent if (!Names.CurrentFrame.InsideNameScope && (createdObject is FrameworkElement || createdObject is FrameworkContentElement)) { nameEnumerator.MoveNext(); nameScope.RegisterNameInternal(nameEnumerator.Current, createdObject); } Names.CurrentFrame.Instance = createdObject; }
// Token: 0x06000691 RID: 1681 RVA: 0x00014908 File Offset: 0x00012B08 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 frameworkElement = container as FrameworkElement; bool flag = frameworkElement != null; DependencyObject dependencyObject = null; if (this._text != null) { IAddChild addChild = parent as IAddChild; if (addChild == null) { throw new InvalidOperationException(SR.Get("TypeMustImplementIAddChild", new object[] { parent.GetType().Name })); } addChild.AddText(this._text); } else { dependencyObject = this.CreateDependencyObject(); EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstEnd); FrameworkObject frameworkObject = new FrameworkObject(dependencyObject); Visual3D visual3D = null; bool flag2 = false; if (!frameworkObject.IsValid) { visual3D = (dependencyObject as Visual3D); if (visual3D != null) { flag2 = true; } } bool isFE = frameworkObject.IsFE; if (!flag2) { FrameworkElementFactory.NewNodeBeginInit(isFE, frameworkObject.FE, frameworkObject.FCE); if (StyleHelper.HasResourceDependentsForChild(this._childIndex, ref resourceDependents)) { frameworkObject.HasResourceReference = true; } FrameworkElementFactory.UpdateChildChains(this._childName, this._childIndex, isFE, frameworkObject.FE, frameworkObject.FCE, affectedChildren, ref noChildIndexChildren); FrameworkElementFactory.NewNodeStyledParentProperty(container, flag, isFE, frameworkObject.FE, frameworkObject.FCE); if (this._childIndex != -1) { StyleHelper.CreateInstanceDataForChild(dataField, container, dependencyObject, this._childIndex, this._frameworkTemplate.HasInstanceValues, ref this._frameworkTemplate.ChildRecordFromChildIndex); } if (this.HasLoadedChangeHandler) { BroadcastEventHelper.AddHasLoadedChangeHandlerFlagInAncestry(dependencyObject); } } else if (this._childName != null) { affectedChildren.Add(dependencyObject); } else { if (noChildIndexChildren == null) { noChildIndexChildren = new List <DependencyObject>(4); } noChildIndexChildren.Add(dependencyObject); } if (container == parent) { TemplateNameScope value = new TemplateNameScope(container); NameScope.SetNameScope(dependencyObject, value); if (flag) { frameworkElement.TemplateChild = frameworkObject.FE; } else { FrameworkElementFactory.AddNodeToLogicalTree((FrameworkContentElement)parent, this._type, isFE, frameworkObject.FE, frameworkObject.FCE); } } else { this.AddNodeToParent(parent, frameworkObject); } if (!flag2) { StyleHelper.InvalidatePropertiesOnTemplateNode(container, frameworkObject, this._childIndex, ref this._frameworkTemplate.ChildRecordFromChildIndex, false, this); } else { for (int i = 0; i < this.PropertyValues.Count; i++) { if (this.PropertyValues[i].ValueType != PropertyValueType.Set) { throw new NotSupportedException(SR.Get("Template3DValueOnly", new object[] { this.PropertyValues[i].Property })); } object obj = this.PropertyValues[i].ValueInternal; Freezable freezable = obj as Freezable; if (freezable != null && !freezable.CanFreeze) { obj = freezable.Clone(); } MarkupExtension markupExtension = obj as MarkupExtension; if (markupExtension != null) { ProvideValueServiceProvider provideValueServiceProvider = new ProvideValueServiceProvider(); provideValueServiceProvider.SetData(visual3D, this.PropertyValues[i].Property); obj = markupExtension.ProvideValue(provideValueServiceProvider); } visual3D.SetValue(this.PropertyValues[i].Property, obj); } } for (FrameworkElementFactory frameworkElementFactory = this._firstChild; frameworkElementFactory != null; frameworkElementFactory = frameworkElementFactory._nextSibling) { frameworkElementFactory.InstantiateTree(dataField, container, dependencyObject, affectedChildren, ref noChildIndexChildren, ref resourceDependents); } if (!flag2) { FrameworkElementFactory.NewNodeEndInit(isFE, frameworkObject.FE, frameworkObject.FCE); } } return(dependencyObject); }