Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / FrameworkTemplate.cs / 1407647 / FrameworkTemplate.cs
//------------------------------------------------------------------------------------ // // File: FrameworkTemplate.cs // // Description: // A generic class that allow instantiation of a tree of Framework[Content]Elements. // // Copyright (C) 2005 by Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------------- using MS.Internal; // Helper using MS.Utility; // ChildValueLookupList using System.ComponentModel; // DesignerSerializationVisibility, DefaultValueAttribute using System.Collections; // Hashtable using System.Collections.Generic; // Listusing System.Collections.Specialized; // HybridDictionary using System.Diagnostics; // Debug using System.Runtime.CompilerServices; // ConditionalWeakTable using System.Security; // SecurityCriticalAttribute, SecurityTreatAsSafe using System.Threading; // Interlocked using System.Windows.Media.Animation; // Timeline using System.Windows.Markup; // XamlTemplateSerializer, ContentPropertyAttribute using System.Windows.Media; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Threading; // DispatcherObject using System.Xaml; using System.Windows.Data; using System.Globalization; using MS.Internal.Xaml.Context; namespace System.Windows { /// /// A generic class that allow instantiation of a /// tree of Framework[Content]Elements. /// // The ContentProperty really isn't VisualTree in WPF4 and later. Right now, we continue to lie for compat with Cider. [ContentProperty("VisualTree")] [Localizability(LocalizationCategory.NeverLocalize)] // All properties on template are not localizable public abstract class FrameworkTemplate : DispatcherObject, INameScope, ISealable, IHaveResources, IQueryAmbient { ////// protected FrameworkTemplate() { #if DEBUG _debugInstanceCounter = ++_globalDebugInstanceCounter; #endif } #region PublicMethods ////// Subclasses must override this method if they need to /// impose additional rules for the TemplatedParent /// protected virtual void ValidateTemplatedParent(FrameworkElement templatedParent) { Debug.Assert(templatedParent != null, "Must have a non-null FE TemplatedParent."); } #endregion PublicMethods #region PublicProperties ////// Says if this template has been sealed /// public bool IsSealed { get { // Verify Context Access VerifyAccess(); return _sealed; } } ////// Root node of the template /// public FrameworkElementFactory VisualTree { get { // Verify Context Access VerifyAccess(); return _templateRoot; } set { // Verify Context Access VerifyAccess(); CheckSealed(); ValidateVisualTree(value); _templateRoot = value; } } ////// Indicates if the VisualTree property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeVisualTree() { // Verify Context Access VerifyAccess(); return HasContent || VisualTree != null; } /* ////// The content of this template. The alternate form of template content is the VisualTree property. /// One of these two properties may be set, but not both. Note that getting this property can cause /// the content to created, which could be expensive. So to merely check if Content is set to a non-null /// value, use the HasContent property. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public FrameworkElement Content { get { // Verify Context Access VerifyAccess(); if( HasContent ) { return LoadTemplateContent() as FrameworkElement; } else { return null; } } } ////// Returns true if the Content property should be serialized /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeContent() { // Verify Context Access VerifyAccess(); return HasContent || VisualTree != null; } ////// Resets the Content property to null; /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetContent() { // Verify Context Access VerifyAccess(); _templateRoot = null; } */ ////// The property which records/plays the XamlNodes for the template. /// [Ambient] [DefaultValue(null)] public TemplateContent Template { get { return _templateHolder; } set { CheckSealed(); if (!_hasXamlNodeContent) { value.OwnerTemplate = this; value.ParseXaml(); _templateHolder = value; _hasXamlNodeContent = true; } else { throw new System.Windows.Markup.XamlParseException(SR.Get(SRID.TemplateContentSetTwice)); } } } ////// The collection of resources that can be /// consumed by the container and its sub-tree. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Ambient] public ResourceDictionary Resources { get { // Verify Context Access VerifyAccess(); if ( _resources == null ) { _resources = new ResourceDictionary(); // A Template ResourceDictionary can be accessed across threads _resources.CanBeAccessedAcrossThreads = true; } if ( IsSealed ) { _resources.IsReadOnly = true; } return _resources; } set { // Verify Context Access VerifyAccess(); if ( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "Template")); } _resources = value; if (_resources != null) { // A Template ResourceDictionary can be accessed across threads _resources.CanBeAccessedAcrossThreads = true; } } } ResourceDictionary IHaveResources.Resources { get { return Resources; } set { Resources = value; } } ////// Tries to find a Reosurce for the given resourceKey in the current /// template's ResourceDictionary. /// internal object FindResource(object resourceKey, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference) { if ((_resources != null) && _resources.Contains(resourceKey)) { bool canCache; return _resources.FetchResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache); } return DependencyProperty.UnsetValue; } bool IQueryAmbient.IsAmbientPropertyAvailable(string propertyName) { // We want to make sure that StaticResource resolution checks the .Resources // Ie. The Ambient search should look at Resources if it is set. // Even if it wasn't set from XAML (eg. the Ctor (or derived Ctor) added stuff) if (propertyName == "Resources" && _resources == null) { return false; } else if (propertyName == "Template" && !_hasXamlNodeContent) { return false; } return true; } ////// FindName - Finds the element associated with the id defined under this control template. /// Context of the FrameworkElement where this template is applied will be passed /// as parameter. /// /// string name /// context where this template is applied ///the element associated with the Name public Object FindName(string name, FrameworkElement templatedParent) { // Verify Context Access VerifyAccess(); if (templatedParent == null) { throw new ArgumentNullException("templatedParent"); } if (this != templatedParent.TemplateInternal) { throw new InvalidOperationException(SR.Get(SRID.TemplateFindNameInInvalidElement)); } return StyleHelper.FindNameInTemplateContent(templatedParent, name, this); } #endregion PublicProperties #region INameScope ////// Registers the name - Context combination /// /// Name to register /// Element where name is defined public void RegisterName(string name, object scopedElement) { // Verify Context Access VerifyAccess(); _nameScope.RegisterName(name, scopedElement); } ////// Unregisters the name - element combination /// /// Name of the element public void UnregisterName(string name) { // Verify Context Access VerifyAccess(); _nameScope.UnregisterName(name); } ////// Find the element given name /// /// Name of the element object INameScope.FindName(string name) { // Verify Context Access VerifyAccess(); return _nameScope.FindName(name); } private NameScope _nameScope = new NameScope(); #endregion INameScope #region NonPublicMethods // =========================================================================== // Validation methods // =========================================================================== // Validate against the following rules // 1. The VisualTree's root must be a FrameworkElement. private void ValidateVisualTree(FrameworkElementFactory templateRoot) { // The VisualTree's root must be a FrameworkElement. if (templateRoot != null && typeof(FrameworkContentElement).IsAssignableFrom(templateRoot.Type)) { throw new ArgumentException(SR.Get(SRID.VisualTreeRootIsFrameworkElement, typeof(FrameworkElement).Name, templateRoot.Type.Name)); } } // ============================================================================ // These methods are invoked when a Template is being sealed // =========================================================================== #region Seal internal virtual void ProcessTemplateBeforeSeal() { } ////// Seal this FrameworkTemplate /// public void Seal() { // Verify Context Access VerifyAccess(); StyleHelper.SealTemplate( this, ref _sealed, _templateRoot, TriggersInternal, _resources, ChildIndexFromChildName, ref ChildRecordFromChildIndex, ref TriggerSourceRecordFromChildIndex, ref ContainerDependents, ref ResourceDependents, ref EventDependents, ref _triggerActions, ref _dataTriggerRecordFromBinding, ref _hasInstanceValues, ref _eventHandlersStore); //Let go of the TemplateContent object to reduce survived allocations. //Need to keep while parsing due to ambient lookup of DependencyPropertyConverter. if (_templateHolder != null) { _templateHolder.ResetTemplateLoadData(); } } // Subclasses need to call this method before any changes to their state. internal void CheckSealed() { if (_sealed) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "Template")); } } // compute and cache the flags for ResourceReferences internal void SetResourceReferenceState() { Debug.Assert(!_sealed, "call this method before template is sealed"); StyleHelper.SortResourceDependents(ref ResourceDependents); for (int i = 0; i < ResourceDependents.Count; ++i) { if (ResourceDependents[i].ChildIndex == 0) { WriteInternalFlag(InternalFlags.HasContainerResourceReferences, true); } else { WriteInternalFlag(InternalFlags.HasChildResourceReferences, true); } } } #endregion Seal // ============================================================================ // These methods are invoked to during a call call to // FE.EnsureVisual or FCE.EnsureLogical // ============================================================================ #region InstantiateSubTree // // This method // Creates the VisualTree // //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 internal bool ApplyTemplateContent( UncommonFieldtemplateDataField, FrameworkElement container) { #if STYLE_TRACE _timer.Begin(); #endif if (TraceDependencyProperty.IsEnabled) { TraceDependencyProperty.Trace( TraceEventType.Start, TraceDependencyProperty.ApplyTemplateContent, container, this); } ValidateTemplatedParent(container); bool visualsCreated = StyleHelper.ApplyTemplateContent(templateDataField, container, _templateRoot, _lastChildIndex, ChildIndexFromChildName, this); if (TraceDependencyProperty.IsEnabled) { TraceDependencyProperty.Trace( TraceEventType.Stop, TraceDependencyProperty.ApplyTemplateContent, container, this); } #if STYLE_TRACE _timer.End(); if (visualsCreated) { string label = container.ID; if (label == null || label.Length == 0) label = container.GetHashCode().ToString(); Console.WriteLine(" Style.VT created for {0} {1} in {2:f2} msec", container.GetType().Name, label, _timer.TimeOfLastPeriod); } #endif return visualsCreated; } #endregion InstantiateSubTree //+----------------------------------------------------------------------------------------------------- // // LoadContent // // Load the content of a template, returning the root element of the content. The second version // loads the template content for use on an FE (i.e. under FrameworkElement.ApplyTemplate). The // first version is used by the Content property for serialization, no optimization is // performed, and TemplateBinding's show up as TemplateBindingExpression's. So it's just a normal // tree. // //+------------------------------------------------------------------------------------------------------ /// /// Load the content of a template as an instance of an object. Calling this multiple times /// will return separate instances. /// public DependencyObject LoadContent() { // Verify Context Access VerifyAccess(); if (VisualTree != null) { FrameworkObject frameworkObject = VisualTree.InstantiateUnoptimizedTree(); return frameworkObject.DO; } else { return LoadContent(null, null); } } internal DependencyObject LoadContent( DependencyObject container, ListaffectedChildren) { if (!HasContent) { return null; } // We can't let multiple threads in simultaneously since SchemaContext // is not totally thread safe right now. lock (SystemResources.ThemeDictionaryLock) { return LoadOptimizedTemplateContent(container, null, this._styleConnector, affectedChildren, null); } } // The v3 main parser didn't treat ResourceDictionary as a NameScope, so // GetXamlType(typeof(ResourceDictionary).IsNameScope returns false. However, // the v3 template parser did treat RD as a NameScope. So we need to special-case it. internal static bool IsNameScope(XamlType type) { if (typeof(ResourceDictionary).IsAssignableFrom(type.UnderlyingType)) { return true; } return type.IsNameScope; } /// /// Indicate if this template has optimized content. /// public bool HasContent { get { // Verify Context Access VerifyAccess(); return _hasXamlNodeContent; } } // =========================================================================== // These methods are invoked when the template has an alternate // mechanism of generating a visual tree. // =========================================================================== #region BuildVisualTree // // This method // 1. Is an alternative approach to building a visual tree from a FEF // 2. Is used by ContentPresenter and Hyperlink to host their content // //CASRemoval:[StrongNameIdentityPermissionAttribute(SecurityAction.InheritanceDemand, PublicKey=Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_STRING)] internal virtual bool BuildVisualTree(FrameworkElement container) { return false; } // // This property // 1. Says if this Template is meant to use BuildVisualTree mechanism // to generate a visual tree. // 2. Is used in the following scenario. // We need to preserve the treeState cache on a container node // even after all its logical children have been added. This is so that // construction of the style visual tree nodes can consume the cache. // This method helps us know whether we should retain the cache for // special scenarios when the visual tree is being built via BuildVisualTree // internal bool CanBuildVisualTree { get { return ReadInternalFlag(InternalFlags.CanBuildVisualTree); } set { WriteInternalFlag(InternalFlags.CanBuildVisualTree, value); } } #endregion BuildVisualTree ////// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeResources(XamlDesignerSerializationManager manager) { // Verify Context Access VerifyAccess(); bool shouldSerialize = true; if (manager != null) { shouldSerialize = (manager.XmlWriter == null); } return shouldSerialize; } // Extracts the required flag and returns // bool to indicate if it is set or unset private bool ReadInternalFlag(InternalFlags reqFlag) { return (_flags & reqFlag) != 0; } // Sets or Unsets the required flag based on // the bool argument private void WriteInternalFlag(InternalFlags reqFlag, bool set) { if (set) { _flags |= reqFlag; } else { _flags &= (~reqFlag); } } #endregion NonPublicMethods #region NonPublicProperties private class Frame : XamlFrame { public Frame() { } public XamlType Type { get; set; } public XamlMember Property { get; set; } public bool InsideNameScope { get; set; } public object Instance { get; set; } public override void Reset() { Type = null; Property = null; Instance = null; if (InsideNameScope) { InsideNameScope = false; } } } private XamlContextStack Names; 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; } // 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, ListaffectedChildren, UncommonField templatedNonFeChildrenField) { if (Names == null) { Names = new XamlContextStack(() => 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 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); }; // 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; } /// /// Critical: Accesses and asserts critical LoadPermission /// Safe: The XAML to load comes from _templateHolder.PlayXaml, which is SecurityCritcal and /// guaranteed to have demanded _templateHolder.LoadPermission before being set. /// [SecurityCritical, SecurityTreatAsSafe] private void LoadTemplateXaml(XamlObjectWriter objectWriter) { System.Xaml.XamlReader templateReader = _templateHolder.PlayXaml(); Debug.Assert(templateReader != null, "PlayXaml returned null"); if (_templateHolder.LoadPermission != null) { _templateHolder.LoadPermission.Assert(); try { LoadTemplateXaml(templateReader, objectWriter); } finally { CodeAccessPermission.RevertAssert(); } } else { LoadTemplateXaml(templateReader, objectWriter); } } private void LoadTemplateXaml(System.Xaml.XamlReader templateReader, XamlObjectWriter currentWriter) { try { while (templateReader.Read()) { // We need to call the ObjectWriter first because x:Name & RNPA needs to be registered // before we call InvalidateProperties. currentWriter.WriteNode(templateReader); switch (templateReader.NodeType) { case System.Xaml.XamlNodeType.None: case System.Xaml.XamlNodeType.NamespaceDeclaration: break; case System.Xaml.XamlNodeType.StartObject: { // If parent is a namescope or was inside a nested namescope, make the new frame inside a nested namescope bool isInsideNameScope = Names.Depth > 0 && (IsNameScope(Names.CurrentFrame.Type) || Names.CurrentFrame.InsideNameScope); Names.PushScope(); Names.CurrentFrame.Type = templateReader.Type; if (isInsideNameScope) { Names.CurrentFrame.InsideNameScope = true; } } break; case System.Xaml.XamlNodeType.GetObject: { // If parent is a namescope or was inside a nested namescope, make the new frame inside a nested namescope bool isInsideNameScope = IsNameScope(Names.CurrentFrame.Type) || Names.CurrentFrame.InsideNameScope; Names.PushScope(); Names.CurrentFrame.Type = Names.PreviousFrame.Property.Type; if (isInsideNameScope) { Names.CurrentFrame.InsideNameScope = true; } } break; case System.Xaml.XamlNodeType.StartMember: Names.CurrentFrame.Property = templateReader.Member; break; case System.Xaml.XamlNodeType.EndMember: Names.CurrentFrame.Property = null; break; case System.Xaml.XamlNodeType.EndObject: Names.PopScope(); break; case System.Xaml.XamlNodeType.Value: if (Names.CurrentFrame.Property == XamlLanguage.ConnectionId) { if (_styleConnector != null) { _styleConnector.Connect((int)templateReader.Value, Names.CurrentFrame.Instance); } } break; default: Debug.Assert(false, "Unknown enum value"); break; } } } catch (Exception e) { if (CriticalExceptions.IsCriticalException(e) || e is System.Windows.Markup.XamlParseException) { throw; } System.Windows.Markup.XamlReader.RewrapException(e, null); } } internal static bool IsNameProperty(XamlMember member, XamlType owner) { if (member == owner.GetAliasedProperty(XamlLanguage.Name) || XamlLanguage.Name == member) { return true; } return false; } private void HandleAfterBeginInit(object createdObject, ref DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, TemplateNameScope nameScope, IEnumeratornameEnumerator) { // 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; } private void HandleBeforeProperties(object createdObject, ref DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope) { if (createdObject is FrameworkElement || createdObject is FrameworkContentElement) { // We want to set TemplateChild on the parent if we are dealing with the root // We MUST wait until the object is wired into the Template vis TemplateNameScope.RegisterName if (rootObject == null) { rootObject = WireRootObjectToParent(createdObject, rootObject, container, feContainer, nameScope); } InvalidatePropertiesOnTemplate(container, createdObject); } } private static DependencyObject WireRootObjectToParent(object createdObject, DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope) { rootObject = createdObject as DependencyObject; if (rootObject != null) { // Add the root to the appropriate tree. if (feContainer != null) { // Put the root object into FE.Templatechild (must be a UIElement). UIElement rootElement = rootObject as UIElement; if (rootElement == null) { throw new InvalidOperationException(SR.Get(SRID.TemplateMustBeFE, new object[] { rootObject.GetType().FullName })); } feContainer.TemplateChild = rootElement; Debug.Assert(!(rootElement is FrameworkElement) || ((FrameworkElement)rootElement).TemplateChildIndex != -1); } // If we have a container that is not a FE, add to the logical tree of the FEF else if (container != null) { FrameworkElement feResult; FrameworkContentElement fceResult; Helper.DowncastToFEorFCE(rootObject, out feResult, out fceResult, true); FrameworkElementFactory.AddNodeToLogicalTree((FrameworkContentElement)container, rootObject.GetType(), feResult != null, feResult, fceResult); } // Set the TemplateNameScope on the root if (NameScope.GetNameScope(rootObject) == null) { NameScope.SetNameScope(rootObject, nameScope); } } return rootObject; } 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); } } } } //+--------------------------------------------------------------------------------------------------------------- // // SetTemplateParentValues // // This method takes the "template parent values" (those that look like local values in the template), which // are ordinarily shared, and sets them as local values on the FE/FCE that was just created. This is used // during serialization. // //+---------------------------------------------------------------------------------------------------------------- internal static void SetTemplateParentValues( string name, object element, FrameworkTemplate frameworkTemplate, ref ProvideValueServiceProvider provideValueServiceProvider) { int childIndex; // Loop through the shared values, and set them onto the element. FrugalStructList childRecordFromChildIndex; HybridDictionary childIndexFromChildName; // Seal the template, and get the name->index and index->ChildRecord mappings if (!frameworkTemplate.IsSealed) { frameworkTemplate.Seal(); } childIndexFromChildName = frameworkTemplate.ChildIndexFromChildName; childRecordFromChildIndex = frameworkTemplate.ChildRecordFromChildIndex; // Calculate the child index childIndex = StyleHelper.QueryChildIndexFromChildName(name, childIndexFromChildName); // Do we have a ChildRecord for this index (i.e., there's some property set on it)? if (childIndex < childRecordFromChildIndex.Count) { // Yes, get the record. ChildRecord child = (ChildRecord)childRecordFromChildIndex[childIndex]; // Loop through the properties which are in some way set on this child for (int i = 0; i < child.ValueLookupListFromProperty.Count; i++) { // And for each of those properties, loop through the potential values specified in the template // for that property on that child. for (int j = 0; j < child.ValueLookupListFromProperty.Entries[i].Value.Count; j++) { // Get this value (in valueLookup) ChildValueLookup valueLookup; valueLookup = (ChildValueLookup)child.ValueLookupListFromProperty.Entries[i].Value.List[j]; // See if this value is one that is considered to be locally set on the child element if (valueLookup.LookupType == ValueLookupType.Simple || valueLookup.LookupType == ValueLookupType.Resource || valueLookup.LookupType == ValueLookupType.TemplateBinding) { // This shared value is for this element, so we'll set it. object value = valueLookup.Value; // If this is a TemplateBinding, put on an expression for it, so that it can // be represented correctly (e.g. for serialization). Otherwise, keep it as an ME. if (valueLookup.LookupType == ValueLookupType.TemplateBinding) { value = new TemplateBindingExpression(value as TemplateBindingExtension); } // Dynamic resources need to be converted to an expression also. else if (valueLookup.LookupType == ValueLookupType.Resource) { value = new ResourceReferenceExpression(value); } // Bindings are handled as just an ME // Set the value directly onto the element. MarkupExtension me = value as MarkupExtension; if (me != null) { // This is provided for completeness, but really there's only a few // MEs that survive TemplateBamlRecordReader. E.g. NullExtension would // have been converted to a null by now. There's only a few MEs that // are preserved, e.g. Binding and DynamicResource. Other MEs, such as // StaticResource, wouldn't be able to ProvideValue here, because we don't // have a ParserContext. if (provideValueServiceProvider == null) { provideValueServiceProvider = new ProvideValueServiceProvider(); } provideValueServiceProvider.SetData(element, valueLookup.Property); value = me.ProvideValue(provideValueServiceProvider); provideValueServiceProvider.ClearData(); } (element as DependencyObject).SetValue(valueLookup.Property, value); //sharedDp.Dp, value ); } } } } } // // TargetType for ControlTemplate // internal virtual Type TargetTypeInternal { get { return null; } } // Subclasses must provide a way for the parser to directly set the // target type. internal abstract void SetTargetTypeInternal(Type targetType); // // DataType for DataTemplate // internal virtual object DataTypeInternal { get { return null; } } #region ISealable /// /// Can this template be sealed /// bool ISealable.CanSeal { get { return true; } } ////// Is this template sealed /// bool ISealable.IsSealed { get { return IsSealed; } } ////// Seal this template /// void ISealable.Seal() { Seal(); } #endregion ISealable // // Collection of Triggers for a ControlTemplate // internal virtual TriggerCollection TriggersInternal { get { return null; } } // // Says if this template contains any resource references // internal bool HasResourceReferences { get { return ResourceDependents.Count > 0; } } // // Says if this template contains any resource references for properties on the container // internal bool HasContainerResourceReferences { get { return ReadInternalFlag(InternalFlags.HasContainerResourceReferences); } } // // Says if this template contains any resource references for properties on children // internal bool HasChildResourceReferences { get { return ReadInternalFlag(InternalFlags.HasChildResourceReferences); } } // // Says if this template contains any event handlers // internal bool HasEventDependents { get { return (EventDependents.Count > 0); } } // // Says if this template contains any per-instance values // internal bool HasInstanceValues { get { return _hasInstanceValues; } } // // Says if we have anything listening for the Loaded or Unloaded // event (used for an optimization in FrameworkElement). // internal bool HasLoadedChangeHandler { get { return ReadInternalFlag(InternalFlags.HasLoadedChangeHandler); } set { WriteInternalFlag(InternalFlags.HasLoadedChangeHandler, value); } } // // Give the template its own copy of the parser context. It needs a copy, because it's // going to use it later on every application. // internal void CopyParserContext(ParserContext parserContext) { _parserContext = parserContext.ScopedCopy(false /*copyNameScopeStack*/ ); // We need to clear the Journal bit, because we know we won't be able to honor it correctly. // Journaling journals the properties in the logical tree, so doesn't journal properties in the // Template/Resources. This shouldn't be hard-coded here, but is an internal solution for V1. _parserContext.SkipJournaledProperties = false; } // // ParserContext cached with this template. // internal ParserContext ParserContext { get { return _parserContext; } } // // Store all the event handlers for this Style TargetType // internal EventHandlersStore EventHandlersStore { get { return _eventHandlersStore; } } // // Style and component connectors used during template // application. // internal IStyleConnector StyleConnector { get { return _styleConnector; } set { _styleConnector = value; } } internal IComponentConnector ComponentConnector { get { return _componentConnector; } set { _componentConnector = value; } } // // Prefetched values for static resources // internal object[] StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } internal bool HasXamlNodeContent { get { return _hasXamlNodeContent; } } internal HybridDictionary ChildIndexFromChildName { get { return _childIndexFromChildName; } } internal DictionaryChildTypeFromChildIndex { get { return _childTypeFromChildIndex; } } internal int LastChildIndex { get { return _lastChildIndex; } set { _lastChildIndex = value; } } internal List ChildNames { get { return _childNames; } } #endregion NonPublicProperties #region Data private InternalFlags _flags; private bool _sealed; // passed by ref, so cannot use flags internal bool _hasInstanceValues; // passed by ref, so cannot use flags private ParserContext _parserContext; private IStyleConnector _styleConnector; private IComponentConnector _componentConnector; // If we're a FEF-based template, we'll have a _templateRoot. private FrameworkElementFactory _templateRoot; private TemplateContent _templateHolder; private bool _hasXamlNodeContent; // // Used to generate childIndex for each TemplateNode // private HybridDictionary _childIndexFromChildName = new HybridDictionary(); private Dictionary _childTypeFromChildIndex = new Dictionary (); private int _lastChildIndex = 1; // 0 means "self" (container), no instance ever has index 0 private List _childNames = new List (); // // Resource dictionary associated with this template. // internal ResourceDictionary _resources = null; // // Used by EventTrigger: Maps a RoutedEventID to a set of TriggerAction objects // to be performed. // internal HybridDictionary _triggerActions = null; // // Shared tables used during GetValue // internal FrugalStructList ChildRecordFromChildIndex = new FrugalStructList (); // Indexed by Child.ChildIndex // // Shared tables used during OnTriggerSourcePropertyInvalidated // internal FrugalStructList > TriggerSourceRecordFromChildIndex = new FrugalStructList >(); // Dictionary of property triggers that have TriggerActions, keyed via DP.GlobalIndex affecting those triggers. // Each trigger can be listed multiple times, if they are dependent on multiple properties. internal FrugalMap PropertyTriggersWithActions; // // Shared tables used during OnStyleInvalidated/OnTemplateInvalidated/InvalidateTree // // Properties driven on the container (by the Style) that should be // invalidated when the style gets applied/unapplied. These properties // could have been set via Style.SetValue or VisualTrigger.SetValue internal FrugalStructList ContainerDependents = new FrugalStructList (); // Properties driven by a resource that should be invalidated // when a resource dictionary changes or when the tree changes // or when a Style is Invalidated internal FrugalStructList ResourceDependents = new FrugalStructList (); // Data trigger information. An entry for each Binding that appears in a // condition of a data trigger. // Synchronized: Covered by Style instance internal HybridDictionary _dataTriggerRecordFromBinding; // An entry for each Binding that appears in a DataTrigger with EnterAction or ExitAction // This overlaps but should not be the same as _dataTriggerRecordFromBinding above: // A DataTrigger can have Setters but no EnterAction/ExitAction. (The reverse can also be true.) internal HybridDictionary DataTriggersWithActions = null; // It is possible for trigger events to occur before template expansion has // taken place. In these cases, we cannot resolve the appropriate target name // at that time. We defer invoking these actions until template expansion // is complete. // The key to the dictionary are the individual object instances that this // template applies to. (We might be holding deferred actions for multiple // objects.) // The value of the dictionary is the trigger object and one of its action // lists stored in the struct DeferredAction. internal ConditionalWeakTable > DeferredActions = null; // Keep track of the template children elements for which the template has a Loaded // or Unloaded listener. internal class TemplateChildLoadedFlags { public bool HasLoadedChangedHandler; public bool HasUnloadedChangedHandler; } internal HybridDictionary _TemplateChildLoadedDictionary = new HybridDictionary(); // // Shared tables used during Event Routing // // Events driven by a this style. An entry for every childIndex that has associated events. // childIndex '0' is used to represent events set ont he style's TargetType. This data-structure // will be frequently looked up during event routing. internal ItemStructList EventDependents = new ItemStructList (1); // Used to store a private delegate that called back during event // routing so we can process EventTriggers private EventHandlersStore _eventHandlersStore = null; // Prefetched values for StaticResources private object[] _staticResourceValues = null; #if STYLE_TRACE // Time that is used only when style tracing is enabled private MS.Internal.Utility.HFTimer _timer = new MS.Internal.Utility.HFTimer(); #endif #if DEBUG // Debug counter for intelligent breakpoints. static private int _globalDebugInstanceCounter = 0; private int _debugInstanceCounter; #endif [Flags] private enum InternalFlags : uint { //Sealed = 0x00000001, //HasInstanceValues = 0x00000002, CanBuildVisualTree = 0x00000004, HasLoadedChangeHandler = 0x00000008, HasContainerResourceReferences = 0x00000010, HasChildResourceReferences = 0x00000020, } #endregion Data } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------------ // // File: FrameworkTemplate.cs // // Description: // A generic class that allow instantiation of a tree of Framework[Content]Elements. // // Copyright (C) 2005 by Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------------- using MS.Internal; // Helper using MS.Utility; // ChildValueLookupList using System.ComponentModel; // DesignerSerializationVisibility, DefaultValueAttribute using System.Collections; // Hashtable using System.Collections.Generic; // List using System.Collections.Specialized; // HybridDictionary using System.Diagnostics; // Debug using System.Runtime.CompilerServices; // ConditionalWeakTable using System.Security; // SecurityCriticalAttribute, SecurityTreatAsSafe using System.Threading; // Interlocked using System.Windows.Media.Animation; // Timeline using System.Windows.Markup; // XamlTemplateSerializer, ContentPropertyAttribute using System.Windows.Media; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Threading; // DispatcherObject using System.Xaml; using System.Windows.Data; using System.Globalization; using MS.Internal.Xaml.Context; namespace System.Windows { /// /// A generic class that allow instantiation of a /// tree of Framework[Content]Elements. /// // The ContentProperty really isn't VisualTree in WPF4 and later. Right now, we continue to lie for compat with Cider. [ContentProperty("VisualTree")] [Localizability(LocalizationCategory.NeverLocalize)] // All properties on template are not localizable public abstract class FrameworkTemplate : DispatcherObject, INameScope, ISealable, IHaveResources, IQueryAmbient { ////// protected FrameworkTemplate() { #if DEBUG _debugInstanceCounter = ++_globalDebugInstanceCounter; #endif } #region PublicMethods ////// Subclasses must override this method if they need to /// impose additional rules for the TemplatedParent /// protected virtual void ValidateTemplatedParent(FrameworkElement templatedParent) { Debug.Assert(templatedParent != null, "Must have a non-null FE TemplatedParent."); } #endregion PublicMethods #region PublicProperties ////// Says if this template has been sealed /// public bool IsSealed { get { // Verify Context Access VerifyAccess(); return _sealed; } } ////// Root node of the template /// public FrameworkElementFactory VisualTree { get { // Verify Context Access VerifyAccess(); return _templateRoot; } set { // Verify Context Access VerifyAccess(); CheckSealed(); ValidateVisualTree(value); _templateRoot = value; } } ////// Indicates if the VisualTree property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeVisualTree() { // Verify Context Access VerifyAccess(); return HasContent || VisualTree != null; } /* ////// The content of this template. The alternate form of template content is the VisualTree property. /// One of these two properties may be set, but not both. Note that getting this property can cause /// the content to created, which could be expensive. So to merely check if Content is set to a non-null /// value, use the HasContent property. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public FrameworkElement Content { get { // Verify Context Access VerifyAccess(); if( HasContent ) { return LoadTemplateContent() as FrameworkElement; } else { return null; } } } ////// Returns true if the Content property should be serialized /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeContent() { // Verify Context Access VerifyAccess(); return HasContent || VisualTree != null; } ////// Resets the Content property to null; /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetContent() { // Verify Context Access VerifyAccess(); _templateRoot = null; } */ ////// The property which records/plays the XamlNodes for the template. /// [Ambient] [DefaultValue(null)] public TemplateContent Template { get { return _templateHolder; } set { CheckSealed(); if (!_hasXamlNodeContent) { value.OwnerTemplate = this; value.ParseXaml(); _templateHolder = value; _hasXamlNodeContent = true; } else { throw new System.Windows.Markup.XamlParseException(SR.Get(SRID.TemplateContentSetTwice)); } } } ////// The collection of resources that can be /// consumed by the container and its sub-tree. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Ambient] public ResourceDictionary Resources { get { // Verify Context Access VerifyAccess(); if ( _resources == null ) { _resources = new ResourceDictionary(); // A Template ResourceDictionary can be accessed across threads _resources.CanBeAccessedAcrossThreads = true; } if ( IsSealed ) { _resources.IsReadOnly = true; } return _resources; } set { // Verify Context Access VerifyAccess(); if ( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "Template")); } _resources = value; if (_resources != null) { // A Template ResourceDictionary can be accessed across threads _resources.CanBeAccessedAcrossThreads = true; } } } ResourceDictionary IHaveResources.Resources { get { return Resources; } set { Resources = value; } } ////// Tries to find a Reosurce for the given resourceKey in the current /// template's ResourceDictionary. /// internal object FindResource(object resourceKey, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference) { if ((_resources != null) && _resources.Contains(resourceKey)) { bool canCache; return _resources.FetchResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache); } return DependencyProperty.UnsetValue; } bool IQueryAmbient.IsAmbientPropertyAvailable(string propertyName) { // We want to make sure that StaticResource resolution checks the .Resources // Ie. The Ambient search should look at Resources if it is set. // Even if it wasn't set from XAML (eg. the Ctor (or derived Ctor) added stuff) if (propertyName == "Resources" && _resources == null) { return false; } else if (propertyName == "Template" && !_hasXamlNodeContent) { return false; } return true; } ////// FindName - Finds the element associated with the id defined under this control template. /// Context of the FrameworkElement where this template is applied will be passed /// as parameter. /// /// string name /// context where this template is applied ///the element associated with the Name public Object FindName(string name, FrameworkElement templatedParent) { // Verify Context Access VerifyAccess(); if (templatedParent == null) { throw new ArgumentNullException("templatedParent"); } if (this != templatedParent.TemplateInternal) { throw new InvalidOperationException(SR.Get(SRID.TemplateFindNameInInvalidElement)); } return StyleHelper.FindNameInTemplateContent(templatedParent, name, this); } #endregion PublicProperties #region INameScope ////// Registers the name - Context combination /// /// Name to register /// Element where name is defined public void RegisterName(string name, object scopedElement) { // Verify Context Access VerifyAccess(); _nameScope.RegisterName(name, scopedElement); } ////// Unregisters the name - element combination /// /// Name of the element public void UnregisterName(string name) { // Verify Context Access VerifyAccess(); _nameScope.UnregisterName(name); } ////// Find the element given name /// /// Name of the element object INameScope.FindName(string name) { // Verify Context Access VerifyAccess(); return _nameScope.FindName(name); } private NameScope _nameScope = new NameScope(); #endregion INameScope #region NonPublicMethods // =========================================================================== // Validation methods // =========================================================================== // Validate against the following rules // 1. The VisualTree's root must be a FrameworkElement. private void ValidateVisualTree(FrameworkElementFactory templateRoot) { // The VisualTree's root must be a FrameworkElement. if (templateRoot != null && typeof(FrameworkContentElement).IsAssignableFrom(templateRoot.Type)) { throw new ArgumentException(SR.Get(SRID.VisualTreeRootIsFrameworkElement, typeof(FrameworkElement).Name, templateRoot.Type.Name)); } } // ============================================================================ // These methods are invoked when a Template is being sealed // =========================================================================== #region Seal internal virtual void ProcessTemplateBeforeSeal() { } ////// Seal this FrameworkTemplate /// public void Seal() { // Verify Context Access VerifyAccess(); StyleHelper.SealTemplate( this, ref _sealed, _templateRoot, TriggersInternal, _resources, ChildIndexFromChildName, ref ChildRecordFromChildIndex, ref TriggerSourceRecordFromChildIndex, ref ContainerDependents, ref ResourceDependents, ref EventDependents, ref _triggerActions, ref _dataTriggerRecordFromBinding, ref _hasInstanceValues, ref _eventHandlersStore); //Let go of the TemplateContent object to reduce survived allocations. //Need to keep while parsing due to ambient lookup of DependencyPropertyConverter. if (_templateHolder != null) { _templateHolder.ResetTemplateLoadData(); } } // Subclasses need to call this method before any changes to their state. internal void CheckSealed() { if (_sealed) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "Template")); } } // compute and cache the flags for ResourceReferences internal void SetResourceReferenceState() { Debug.Assert(!_sealed, "call this method before template is sealed"); StyleHelper.SortResourceDependents(ref ResourceDependents); for (int i = 0; i < ResourceDependents.Count; ++i) { if (ResourceDependents[i].ChildIndex == 0) { WriteInternalFlag(InternalFlags.HasContainerResourceReferences, true); } else { WriteInternalFlag(InternalFlags.HasChildResourceReferences, true); } } } #endregion Seal // ============================================================================ // These methods are invoked to during a call call to // FE.EnsureVisual or FCE.EnsureLogical // ============================================================================ #region InstantiateSubTree // // This method // Creates the VisualTree // //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 internal bool ApplyTemplateContent( UncommonFieldtemplateDataField, FrameworkElement container) { #if STYLE_TRACE _timer.Begin(); #endif if (TraceDependencyProperty.IsEnabled) { TraceDependencyProperty.Trace( TraceEventType.Start, TraceDependencyProperty.ApplyTemplateContent, container, this); } ValidateTemplatedParent(container); bool visualsCreated = StyleHelper.ApplyTemplateContent(templateDataField, container, _templateRoot, _lastChildIndex, ChildIndexFromChildName, this); if (TraceDependencyProperty.IsEnabled) { TraceDependencyProperty.Trace( TraceEventType.Stop, TraceDependencyProperty.ApplyTemplateContent, container, this); } #if STYLE_TRACE _timer.End(); if (visualsCreated) { string label = container.ID; if (label == null || label.Length == 0) label = container.GetHashCode().ToString(); Console.WriteLine(" Style.VT created for {0} {1} in {2:f2} msec", container.GetType().Name, label, _timer.TimeOfLastPeriod); } #endif return visualsCreated; } #endregion InstantiateSubTree //+----------------------------------------------------------------------------------------------------- // // LoadContent // // Load the content of a template, returning the root element of the content. The second version // loads the template content for use on an FE (i.e. under FrameworkElement.ApplyTemplate). The // first version is used by the Content property for serialization, no optimization is // performed, and TemplateBinding's show up as TemplateBindingExpression's. So it's just a normal // tree. // //+------------------------------------------------------------------------------------------------------ /// /// Load the content of a template as an instance of an object. Calling this multiple times /// will return separate instances. /// public DependencyObject LoadContent() { // Verify Context Access VerifyAccess(); if (VisualTree != null) { FrameworkObject frameworkObject = VisualTree.InstantiateUnoptimizedTree(); return frameworkObject.DO; } else { return LoadContent(null, null); } } internal DependencyObject LoadContent( DependencyObject container, ListaffectedChildren) { if (!HasContent) { return null; } // We can't let multiple threads in simultaneously since SchemaContext // is not totally thread safe right now. lock (SystemResources.ThemeDictionaryLock) { return LoadOptimizedTemplateContent(container, null, this._styleConnector, affectedChildren, null); } } // The v3 main parser didn't treat ResourceDictionary as a NameScope, so // GetXamlType(typeof(ResourceDictionary).IsNameScope returns false. However, // the v3 template parser did treat RD as a NameScope. So we need to special-case it. internal static bool IsNameScope(XamlType type) { if (typeof(ResourceDictionary).IsAssignableFrom(type.UnderlyingType)) { return true; } return type.IsNameScope; } /// /// Indicate if this template has optimized content. /// public bool HasContent { get { // Verify Context Access VerifyAccess(); return _hasXamlNodeContent; } } // =========================================================================== // These methods are invoked when the template has an alternate // mechanism of generating a visual tree. // =========================================================================== #region BuildVisualTree // // This method // 1. Is an alternative approach to building a visual tree from a FEF // 2. Is used by ContentPresenter and Hyperlink to host their content // //CASRemoval:[StrongNameIdentityPermissionAttribute(SecurityAction.InheritanceDemand, PublicKey=Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_STRING)] internal virtual bool BuildVisualTree(FrameworkElement container) { return false; } // // This property // 1. Says if this Template is meant to use BuildVisualTree mechanism // to generate a visual tree. // 2. Is used in the following scenario. // We need to preserve the treeState cache on a container node // even after all its logical children have been added. This is so that // construction of the style visual tree nodes can consume the cache. // This method helps us know whether we should retain the cache for // special scenarios when the visual tree is being built via BuildVisualTree // internal bool CanBuildVisualTree { get { return ReadInternalFlag(InternalFlags.CanBuildVisualTree); } set { WriteInternalFlag(InternalFlags.CanBuildVisualTree, value); } } #endregion BuildVisualTree ////// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeResources(XamlDesignerSerializationManager manager) { // Verify Context Access VerifyAccess(); bool shouldSerialize = true; if (manager != null) { shouldSerialize = (manager.XmlWriter == null); } return shouldSerialize; } // Extracts the required flag and returns // bool to indicate if it is set or unset private bool ReadInternalFlag(InternalFlags reqFlag) { return (_flags & reqFlag) != 0; } // Sets or Unsets the required flag based on // the bool argument private void WriteInternalFlag(InternalFlags reqFlag, bool set) { if (set) { _flags |= reqFlag; } else { _flags &= (~reqFlag); } } #endregion NonPublicMethods #region NonPublicProperties private class Frame : XamlFrame { public Frame() { } public XamlType Type { get; set; } public XamlMember Property { get; set; } public bool InsideNameScope { get; set; } public object Instance { get; set; } public override void Reset() { Type = null; Property = null; Instance = null; if (InsideNameScope) { InsideNameScope = false; } } } private XamlContextStack Names; 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; } // 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, ListaffectedChildren, UncommonField templatedNonFeChildrenField) { if (Names == null) { Names = new XamlContextStack(() => 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 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); }; // 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; } /// /// Critical: Accesses and asserts critical LoadPermission /// Safe: The XAML to load comes from _templateHolder.PlayXaml, which is SecurityCritcal and /// guaranteed to have demanded _templateHolder.LoadPermission before being set. /// [SecurityCritical, SecurityTreatAsSafe] private void LoadTemplateXaml(XamlObjectWriter objectWriter) { System.Xaml.XamlReader templateReader = _templateHolder.PlayXaml(); Debug.Assert(templateReader != null, "PlayXaml returned null"); if (_templateHolder.LoadPermission != null) { _templateHolder.LoadPermission.Assert(); try { LoadTemplateXaml(templateReader, objectWriter); } finally { CodeAccessPermission.RevertAssert(); } } else { LoadTemplateXaml(templateReader, objectWriter); } } private void LoadTemplateXaml(System.Xaml.XamlReader templateReader, XamlObjectWriter currentWriter) { try { while (templateReader.Read()) { // We need to call the ObjectWriter first because x:Name & RNPA needs to be registered // before we call InvalidateProperties. currentWriter.WriteNode(templateReader); switch (templateReader.NodeType) { case System.Xaml.XamlNodeType.None: case System.Xaml.XamlNodeType.NamespaceDeclaration: break; case System.Xaml.XamlNodeType.StartObject: { // If parent is a namescope or was inside a nested namescope, make the new frame inside a nested namescope bool isInsideNameScope = Names.Depth > 0 && (IsNameScope(Names.CurrentFrame.Type) || Names.CurrentFrame.InsideNameScope); Names.PushScope(); Names.CurrentFrame.Type = templateReader.Type; if (isInsideNameScope) { Names.CurrentFrame.InsideNameScope = true; } } break; case System.Xaml.XamlNodeType.GetObject: { // If parent is a namescope or was inside a nested namescope, make the new frame inside a nested namescope bool isInsideNameScope = IsNameScope(Names.CurrentFrame.Type) || Names.CurrentFrame.InsideNameScope; Names.PushScope(); Names.CurrentFrame.Type = Names.PreviousFrame.Property.Type; if (isInsideNameScope) { Names.CurrentFrame.InsideNameScope = true; } } break; case System.Xaml.XamlNodeType.StartMember: Names.CurrentFrame.Property = templateReader.Member; break; case System.Xaml.XamlNodeType.EndMember: Names.CurrentFrame.Property = null; break; case System.Xaml.XamlNodeType.EndObject: Names.PopScope(); break; case System.Xaml.XamlNodeType.Value: if (Names.CurrentFrame.Property == XamlLanguage.ConnectionId) { if (_styleConnector != null) { _styleConnector.Connect((int)templateReader.Value, Names.CurrentFrame.Instance); } } break; default: Debug.Assert(false, "Unknown enum value"); break; } } } catch (Exception e) { if (CriticalExceptions.IsCriticalException(e) || e is System.Windows.Markup.XamlParseException) { throw; } System.Windows.Markup.XamlReader.RewrapException(e, null); } } internal static bool IsNameProperty(XamlMember member, XamlType owner) { if (member == owner.GetAliasedProperty(XamlLanguage.Name) || XamlLanguage.Name == member) { return true; } return false; } private void HandleAfterBeginInit(object createdObject, ref DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, TemplateNameScope nameScope, IEnumeratornameEnumerator) { // 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; } private void HandleBeforeProperties(object createdObject, ref DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope) { if (createdObject is FrameworkElement || createdObject is FrameworkContentElement) { // We want to set TemplateChild on the parent if we are dealing with the root // We MUST wait until the object is wired into the Template vis TemplateNameScope.RegisterName if (rootObject == null) { rootObject = WireRootObjectToParent(createdObject, rootObject, container, feContainer, nameScope); } InvalidatePropertiesOnTemplate(container, createdObject); } } private static DependencyObject WireRootObjectToParent(object createdObject, DependencyObject rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope) { rootObject = createdObject as DependencyObject; if (rootObject != null) { // Add the root to the appropriate tree. if (feContainer != null) { // Put the root object into FE.Templatechild (must be a UIElement). UIElement rootElement = rootObject as UIElement; if (rootElement == null) { throw new InvalidOperationException(SR.Get(SRID.TemplateMustBeFE, new object[] { rootObject.GetType().FullName })); } feContainer.TemplateChild = rootElement; Debug.Assert(!(rootElement is FrameworkElement) || ((FrameworkElement)rootElement).TemplateChildIndex != -1); } // If we have a container that is not a FE, add to the logical tree of the FEF else if (container != null) { FrameworkElement feResult; FrameworkContentElement fceResult; Helper.DowncastToFEorFCE(rootObject, out feResult, out fceResult, true); FrameworkElementFactory.AddNodeToLogicalTree((FrameworkContentElement)container, rootObject.GetType(), feResult != null, feResult, fceResult); } // Set the TemplateNameScope on the root if (NameScope.GetNameScope(rootObject) == null) { NameScope.SetNameScope(rootObject, nameScope); } } return rootObject; } 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); } } } } //+--------------------------------------------------------------------------------------------------------------- // // SetTemplateParentValues // // This method takes the "template parent values" (those that look like local values in the template), which // are ordinarily shared, and sets them as local values on the FE/FCE that was just created. This is used // during serialization. // //+---------------------------------------------------------------------------------------------------------------- internal static void SetTemplateParentValues( string name, object element, FrameworkTemplate frameworkTemplate, ref ProvideValueServiceProvider provideValueServiceProvider) { int childIndex; // Loop through the shared values, and set them onto the element. FrugalStructList childRecordFromChildIndex; HybridDictionary childIndexFromChildName; // Seal the template, and get the name->index and index->ChildRecord mappings if (!frameworkTemplate.IsSealed) { frameworkTemplate.Seal(); } childIndexFromChildName = frameworkTemplate.ChildIndexFromChildName; childRecordFromChildIndex = frameworkTemplate.ChildRecordFromChildIndex; // Calculate the child index childIndex = StyleHelper.QueryChildIndexFromChildName(name, childIndexFromChildName); // Do we have a ChildRecord for this index (i.e., there's some property set on it)? if (childIndex < childRecordFromChildIndex.Count) { // Yes, get the record. ChildRecord child = (ChildRecord)childRecordFromChildIndex[childIndex]; // Loop through the properties which are in some way set on this child for (int i = 0; i < child.ValueLookupListFromProperty.Count; i++) { // And for each of those properties, loop through the potential values specified in the template // for that property on that child. for (int j = 0; j < child.ValueLookupListFromProperty.Entries[i].Value.Count; j++) { // Get this value (in valueLookup) ChildValueLookup valueLookup; valueLookup = (ChildValueLookup)child.ValueLookupListFromProperty.Entries[i].Value.List[j]; // See if this value is one that is considered to be locally set on the child element if (valueLookup.LookupType == ValueLookupType.Simple || valueLookup.LookupType == ValueLookupType.Resource || valueLookup.LookupType == ValueLookupType.TemplateBinding) { // This shared value is for this element, so we'll set it. object value = valueLookup.Value; // If this is a TemplateBinding, put on an expression for it, so that it can // be represented correctly (e.g. for serialization). Otherwise, keep it as an ME. if (valueLookup.LookupType == ValueLookupType.TemplateBinding) { value = new TemplateBindingExpression(value as TemplateBindingExtension); } // Dynamic resources need to be converted to an expression also. else if (valueLookup.LookupType == ValueLookupType.Resource) { value = new ResourceReferenceExpression(value); } // Bindings are handled as just an ME // Set the value directly onto the element. MarkupExtension me = value as MarkupExtension; if (me != null) { // This is provided for completeness, but really there's only a few // MEs that survive TemplateBamlRecordReader. E.g. NullExtension would // have been converted to a null by now. There's only a few MEs that // are preserved, e.g. Binding and DynamicResource. Other MEs, such as // StaticResource, wouldn't be able to ProvideValue here, because we don't // have a ParserContext. if (provideValueServiceProvider == null) { provideValueServiceProvider = new ProvideValueServiceProvider(); } provideValueServiceProvider.SetData(element, valueLookup.Property); value = me.ProvideValue(provideValueServiceProvider); provideValueServiceProvider.ClearData(); } (element as DependencyObject).SetValue(valueLookup.Property, value); //sharedDp.Dp, value ); } } } } } // // TargetType for ControlTemplate // internal virtual Type TargetTypeInternal { get { return null; } } // Subclasses must provide a way for the parser to directly set the // target type. internal abstract void SetTargetTypeInternal(Type targetType); // // DataType for DataTemplate // internal virtual object DataTypeInternal { get { return null; } } #region ISealable /// /// Can this template be sealed /// bool ISealable.CanSeal { get { return true; } } ////// Is this template sealed /// bool ISealable.IsSealed { get { return IsSealed; } } ////// Seal this template /// void ISealable.Seal() { Seal(); } #endregion ISealable // // Collection of Triggers for a ControlTemplate // internal virtual TriggerCollection TriggersInternal { get { return null; } } // // Says if this template contains any resource references // internal bool HasResourceReferences { get { return ResourceDependents.Count > 0; } } // // Says if this template contains any resource references for properties on the container // internal bool HasContainerResourceReferences { get { return ReadInternalFlag(InternalFlags.HasContainerResourceReferences); } } // // Says if this template contains any resource references for properties on children // internal bool HasChildResourceReferences { get { return ReadInternalFlag(InternalFlags.HasChildResourceReferences); } } // // Says if this template contains any event handlers // internal bool HasEventDependents { get { return (EventDependents.Count > 0); } } // // Says if this template contains any per-instance values // internal bool HasInstanceValues { get { return _hasInstanceValues; } } // // Says if we have anything listening for the Loaded or Unloaded // event (used for an optimization in FrameworkElement). // internal bool HasLoadedChangeHandler { get { return ReadInternalFlag(InternalFlags.HasLoadedChangeHandler); } set { WriteInternalFlag(InternalFlags.HasLoadedChangeHandler, value); } } // // Give the template its own copy of the parser context. It needs a copy, because it's // going to use it later on every application. // internal void CopyParserContext(ParserContext parserContext) { _parserContext = parserContext.ScopedCopy(false /*copyNameScopeStack*/ ); // We need to clear the Journal bit, because we know we won't be able to honor it correctly. // Journaling journals the properties in the logical tree, so doesn't journal properties in the // Template/Resources. This shouldn't be hard-coded here, but is an internal solution for V1. _parserContext.SkipJournaledProperties = false; } // // ParserContext cached with this template. // internal ParserContext ParserContext { get { return _parserContext; } } // // Store all the event handlers for this Style TargetType // internal EventHandlersStore EventHandlersStore { get { return _eventHandlersStore; } } // // Style and component connectors used during template // application. // internal IStyleConnector StyleConnector { get { return _styleConnector; } set { _styleConnector = value; } } internal IComponentConnector ComponentConnector { get { return _componentConnector; } set { _componentConnector = value; } } // // Prefetched values for static resources // internal object[] StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } internal bool HasXamlNodeContent { get { return _hasXamlNodeContent; } } internal HybridDictionary ChildIndexFromChildName { get { return _childIndexFromChildName; } } internal DictionaryChildTypeFromChildIndex { get { return _childTypeFromChildIndex; } } internal int LastChildIndex { get { return _lastChildIndex; } set { _lastChildIndex = value; } } internal List ChildNames { get { return _childNames; } } #endregion NonPublicProperties #region Data private InternalFlags _flags; private bool _sealed; // passed by ref, so cannot use flags internal bool _hasInstanceValues; // passed by ref, so cannot use flags private ParserContext _parserContext; private IStyleConnector _styleConnector; private IComponentConnector _componentConnector; // If we're a FEF-based template, we'll have a _templateRoot. private FrameworkElementFactory _templateRoot; private TemplateContent _templateHolder; private bool _hasXamlNodeContent; // // Used to generate childIndex for each TemplateNode // private HybridDictionary _childIndexFromChildName = new HybridDictionary(); private Dictionary _childTypeFromChildIndex = new Dictionary (); private int _lastChildIndex = 1; // 0 means "self" (container), no instance ever has index 0 private List _childNames = new List (); // // Resource dictionary associated with this template. // internal ResourceDictionary _resources = null; // // Used by EventTrigger: Maps a RoutedEventID to a set of TriggerAction objects // to be performed. // internal HybridDictionary _triggerActions = null; // // Shared tables used during GetValue // internal FrugalStructList ChildRecordFromChildIndex = new FrugalStructList (); // Indexed by Child.ChildIndex // // Shared tables used during OnTriggerSourcePropertyInvalidated // internal FrugalStructList > TriggerSourceRecordFromChildIndex = new FrugalStructList >(); // Dictionary of property triggers that have TriggerActions, keyed via DP.GlobalIndex affecting those triggers. // Each trigger can be listed multiple times, if they are dependent on multiple properties. internal FrugalMap PropertyTriggersWithActions; // // Shared tables used during OnStyleInvalidated/OnTemplateInvalidated/InvalidateTree // // Properties driven on the container (by the Style) that should be // invalidated when the style gets applied/unapplied. These properties // could have been set via Style.SetValue or VisualTrigger.SetValue internal FrugalStructList ContainerDependents = new FrugalStructList (); // Properties driven by a resource that should be invalidated // when a resource dictionary changes or when the tree changes // or when a Style is Invalidated internal FrugalStructList ResourceDependents = new FrugalStructList (); // Data trigger information. An entry for each Binding that appears in a // condition of a data trigger. // Synchronized: Covered by Style instance internal HybridDictionary _dataTriggerRecordFromBinding; // An entry for each Binding that appears in a DataTrigger with EnterAction or ExitAction // This overlaps but should not be the same as _dataTriggerRecordFromBinding above: // A DataTrigger can have Setters but no EnterAction/ExitAction. (The reverse can also be true.) internal HybridDictionary DataTriggersWithActions = null; // It is possible for trigger events to occur before template expansion has // taken place. In these cases, we cannot resolve the appropriate target name // at that time. We defer invoking these actions until template expansion // is complete. // The key to the dictionary are the individual object instances that this // template applies to. (We might be holding deferred actions for multiple // objects.) // The value of the dictionary is the trigger object and one of its action // lists stored in the struct DeferredAction. internal ConditionalWeakTable > DeferredActions = null; // Keep track of the template children elements for which the template has a Loaded // or Unloaded listener. internal class TemplateChildLoadedFlags { public bool HasLoadedChangedHandler; public bool HasUnloadedChangedHandler; } internal HybridDictionary _TemplateChildLoadedDictionary = new HybridDictionary(); // // Shared tables used during Event Routing // // Events driven by a this style. An entry for every childIndex that has associated events. // childIndex '0' is used to represent events set ont he style's TargetType. This data-structure // will be frequently looked up during event routing. internal ItemStructList EventDependents = new ItemStructList (1); // Used to store a private delegate that called back during event // routing so we can process EventTriggers private EventHandlersStore _eventHandlersStore = null; // Prefetched values for StaticResources private object[] _staticResourceValues = null; #if STYLE_TRACE // Time that is used only when style tracing is enabled private MS.Internal.Utility.HFTimer _timer = new MS.Internal.Utility.HFTimer(); #endif #if DEBUG // Debug counter for intelligent breakpoints. static private int _globalDebugInstanceCounter = 0; private int _debugInstanceCounter; #endif [Flags] private enum InternalFlags : uint { //Sealed = 0x00000001, //HasInstanceValues = 0x00000002, CanBuildVisualTree = 0x00000004, HasLoadedChangeHandler = 0x00000008, HasContainerResourceReferences = 0x00000010, HasChildResourceReferences = 0x00000020, } #endregion Data } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DiagnosticSection.cs
- XPathNavigatorReader.cs
- PropertyOverridesDialog.cs
- IconBitmapDecoder.cs
- BaseTransportHeaders.cs
- XslAstAnalyzer.cs
- DataControlImageButton.cs
- UnknownBitmapEncoder.cs
- RijndaelManagedTransform.cs
- BulletDecorator.cs
- FileIOPermission.cs
- Privilege.cs
- SafeNativeMemoryHandle.cs
- StrokeCollectionConverter.cs
- EntityStoreSchemaFilterEntry.cs
- PrintDialog.cs
- FixedSOMTableCell.cs
- PatternMatcher.cs
- MarkupCompilePass1.cs
- XmlNode.cs
- SingleResultAttribute.cs
- ExpressionTextBox.xaml.cs
- MaterializeFromAtom.cs
- HtmlImage.cs
- StreamUpdate.cs
- MediaElement.cs
- SequentialOutput.cs
- DiffuseMaterial.cs
- StickyNoteHelper.cs
- MenuItem.cs
- CalculatedColumn.cs
- MarshalDirectiveException.cs
- LocatorManager.cs
- CollectionCodeDomSerializer.cs
- DeclarativeCatalogPart.cs
- LogicalCallContext.cs
- XmlSerializationReader.cs
- IsolatedStorageFilePermission.cs
- PointLight.cs
- SoapServerMessage.cs
- StylusPointPropertyUnit.cs
- LinkedResourceCollection.cs
- LayoutUtils.cs
- SamlAuthenticationClaimResource.cs
- CheckPair.cs
- InputLanguageManager.cs
- InheritanceAttribute.cs
- ServiceModelEnhancedConfigurationElementCollection.cs
- Activity.cs
- UserNameSecurityToken.cs
- NamedPipeConnectionPoolSettingsElement.cs
- DictionaryManager.cs
- DetailsViewPagerRow.cs
- DesignerCategoryAttribute.cs
- DataGridRowHeaderAutomationPeer.cs
- DropTarget.cs
- ApplicationGesture.cs
- DataTableTypeConverter.cs
- ReservationCollection.cs
- SwitchElementsCollection.cs
- WebPartCollection.cs
- BufferedWebEventProvider.cs
- TokenBasedSetEnumerator.cs
- AvTraceDetails.cs
- WpfPayload.cs
- Int32Rect.cs
- RefreshPropertiesAttribute.cs
- DataGridViewCellStyleChangedEventArgs.cs
- PackageDigitalSignatureManager.cs
- EpmSourceTree.cs
- DataGridColumnEventArgs.cs
- Parallel.cs
- EngineSite.cs
- TypeElementCollection.cs
- OleDbWrapper.cs
- HttpCapabilitiesBase.cs
- SqlDataSourceConfigureSelectPanel.cs
- EdmScalarPropertyAttribute.cs
- InfoCardXmlSerializer.cs
- XmlProcessingInstruction.cs
- Scene3D.cs
- WebResponse.cs
- FrameworkElementFactoryMarkupObject.cs
- HoistedLocals.cs
- PropertyInformationCollection.cs
- UpdatePanelTriggerCollection.cs
- OleDbFactory.cs
- IPPacketInformation.cs
- SettingsAttributeDictionary.cs
- StylusPointPropertyInfo.cs
- DiscardableAttribute.cs
- DBPropSet.cs
- TextCompositionEventArgs.cs
- BaseDataBoundControlDesigner.cs
- PerformanceCounterLib.cs
- TransformerConfigurationWizardBase.cs
- WebBrowserNavigatingEventHandler.cs
- EntityDataReader.cs
- SrgsSemanticInterpretationTag.cs
- ToolStripSeparator.cs