TemplateXamlParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / TemplateXamlParser.cs / 1305600 / TemplateXamlParser.cs

                            /****************************************************************************\ 
*
* File: TemplateXamlParser.cs
*
* Purpose: Class that interfaces with TokenReader and BamlWriter for 
*          parsing Template
* 
* History: 
*    11/22/04:    [....]      Created
* 
* Copyright (C) 2004 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/
 
using System;
using System.Xml; 
using System.IO; 
using System.Text;
using System.Collections; 
using System.ComponentModel;

using System.Diagnostics;
using System.Reflection; 

using MS.Utility; 
 
#if PBTCOMPILER
namespace MS.Internal.Markup 
#else

using System.Windows;
using System.Windows.Threading; 

namespace System.Windows.Markup 
#endif 
{
    ///  
    /// Handles overrides for case when Template is being built to a tree
    /// instead of compiling to a file.
    /// 
    internal class TemplateXamlParser : XamlParser 
    {
 
#region Constructors 

#if !PBTCOMPILER 
        /// 
        /// Constructor.
        /// 
        ///  
        /// Note that we are re-using the token reader, so we'll swap out the XamlParser that
        /// the token reader uses with ourself.  Then restore it when we're done parsing. 
        ///  
        internal TemplateXamlParser(
            XamlTreeBuilder  treeBuilder, 
            XamlReaderHelper       tokenReader,
            ParserContext    parserContext) : this(tokenReader, parserContext)
        {
            _treeBuilder      = treeBuilder; 
        }
 
#endif 

        ///  
        /// Constructor.
        /// 
        /// 
        /// Note that we are re-using the token reader, so we'll swap out the XamlParser that 
        /// the token reader uses with ourself.  Then restore it when we're done parsing.
        ///  
        internal TemplateXamlParser( 
            XamlReaderHelper      tokenReader,
            ParserContext   parserContext) 
        {
            TokenReader       = tokenReader;
            ParserContext     = parserContext;
 
            _previousXamlParser = TokenReader.ControllingXamlParser;
            TokenReader.ControllingXamlParser = this; 
            _startingDepth = TokenReader.XmlReader.Depth; 
        }
 
#endregion Constructors

#region Overrides
 

        ///  
        /// Override of the main switch statement that processes the xaml nodes. 
        /// 
        ///  
        ///  We need to control when cleanup is done and when the calling parse loop
        ///  is exited, so do this here.
        /// 
        internal override void ProcessXamlNode( 
               XamlNode xamlNode,
           ref bool     cleanup, 
           ref bool     done) 
        {
            switch(xamlNode.TokenType) 
            {
                // Ignore some types of xaml nodes, since they are not
                // relevent to template parsing.
                case XamlNodeType.DocumentStart: 
                case XamlNodeType.DocumentEnd:
                    break; 
 
                case XamlNodeType.ElementEnd:
                    base.ProcessXamlNode(xamlNode, ref cleanup, ref done); 
                    // If we're at the depth that we started out, then we must be done.  In that case quit
                    // and restore the XamlParser that the token reader was using before parsing templates.
                    if (_styleModeStack.Depth == 0)
                    { 
                        done = true;      // Stop the template parse
                        cleanup = false;  // Don't close the stream 
                        TokenReader.ControllingXamlParser = _previousXamlParser; 
                    }
                    break; 

                case XamlNodeType.PropertyArrayStart:
                case XamlNodeType.PropertyArrayEnd:
                case XamlNodeType.DefTag: 
                    ThrowException(SRID.TemplateTagNotSupported, xamlNode.TokenType.ToString(),
                                   xamlNode.LineNumber, xamlNode.LinePosition); 
                    break; 

#if PBTCOMPILER 
                case XamlNodeType.EndAttributes:
                    // if there's a DataType present but no x:Key, write out
                    // the key now based on the DataType
                    if (_dataTypePropertyNode != null && _dataTypePropertyNodeDepth == _styleModeStack.Depth) 
                    {
                        if (!_defNameFound) 
                        { 
                            WriteDataTypeKey(_dataTypePropertyNode);
                        } 
                        _dataTypePropertyNode = null;
                        _dataTypePropertyNodeDepth = -1;
                    }
 
                    base.ProcessXamlNode(xamlNode, ref cleanup, ref done);
                    break; 
#endif 

                // Most nodes are handled by the base XamlParser by creating a 
                // normal BamlRecord.
                default:
                    base.ProcessXamlNode(xamlNode, ref cleanup, ref done);
                    break; 
            }
 
        } 

        ///  
        /// Write start of an unknown tag
        /// 
        /// 
        /// For template parsing, the 'Set' tag is an unknown tag, but this will map to a 
        /// Trigger set command.  Store this as an element start record here.
        /// Also 'Set.Value' will map to the a complex Value set portion of the Set command. 
        ///  
        public override void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode)
        { 
            StyleMode mode = _styleModeStack.Mode;

            // Keep mode and other state up-to-date.  This
            // must be called before updating stack. 

             CommonElementStartProcessing(xamlUnknownTagStartNode, null, ref mode); 
            _styleModeStack.Push(mode); 

 
#if PBTCOMPILER
            string localElementFullName = string.Empty;
            int lastIndex = xamlUnknownTagStartNode.Value.LastIndexOf('.');
 
            // if local complex property bail out now and handle in 2nd pass when TypInfo is available
            if (-1 == lastIndex) 
            { 
                NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownTagStartNode.XmlNamespace);
 
                if (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly)
                {
                    localElementFullName = namespaceMaps[0].ClrNamespace + "." + xamlUnknownTagStartNode.Value;
                } 
            }
            else if (IsLocalPass1) 
            { 
                return;
            } 

            if (localElementFullName.Length == 0 || !IsLocalPass1)
            {
#endif 
                // It can be a fairly common error for,
                // , , or  
                // to be specified at the wrong nesting level (See Windows bug 966137).  Detect 
                // these cases to give more meaningful error messages.
                if (xamlUnknownTagStartNode.Value == XamlTemplateSerializer.ControlTemplateTriggersFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.DataTemplateTriggersFullPropertyName ||
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateTriggersFullPropertyName ||
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemsSourceFullPropertyName ||
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemTemplateFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemTemplateSelectorFullPropertyName ||
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemContainerStyleFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemContainerStyleSelectorFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemStringFormatFullPropertyName ||
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateItemBindingGroupFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlTemplateSerializer.HierarchicalDataTemplateAlternationCountFullPropertyName
                    )
                {
                    ThrowException(SRID.TemplateKnownTagWrongLocation, 
                                   xamlUnknownTagStartNode.Value,
                                   xamlUnknownTagStartNode.LineNumber, 
                                   xamlUnknownTagStartNode.LinePosition); 
                }
                else 
                {
                    base.WriteUnknownTagStart(xamlUnknownTagStartNode);
                }
#if PBTCOMPILER 
            }
#endif 
 
         }
 
        /// 
        /// Write Start element for a dictionary key section.
        /// 
        public override void WriteKeyElementStart( 
            XamlElementStartNode xamlKeyElementStartNode)
        { 
            _styleModeStack.Push(StyleMode.Key); 
            base.WriteKeyElementStart(xamlKeyElementStartNode);
        } 

        /// 
        /// Write End element for a dictionary key section
        ///  
        public override void WriteKeyElementEnd(
            XamlElementEndNode xamlKeyElementEndNode) 
        { 
            _styleModeStack.Pop();
            base.WriteKeyElementEnd(xamlKeyElementEndNode); 
        }

        /// 
        /// Write end of an unknown tag 
        /// 
        ///  
        /// For template parsing, the 'Set' tag is an unknown tag, but this will map to a 
        /// Trigger set command.  Store this as an element end record here.
        ///  
        public override void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode)
        {
            if (_inSetterDepth == xamlUnknownTagEndNode.Depth)
            { 
                XamlElementEndNode elementEnd = new XamlElementEndNode(
                                                        xamlUnknownTagEndNode.LineNumber, 
                                                        xamlUnknownTagEndNode.LinePosition, 
                                                        xamlUnknownTagEndNode.Depth);
                base.WriteElementEnd(elementEnd); 
                _inSetterDepth = -1;
            }
            else
            { 
#if PBTCOMPILER
                NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownTagEndNode.XmlNamespace); 
                bool localTag = namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly; 

                if (!localTag || !IsLocalPass1) 
                {
#endif
                   base.WriteUnknownTagEnd(xamlUnknownTagEndNode);
#if PBTCOMPILER 
                }
#endif 
            } 

            _styleModeStack.Pop(); 
        }

        /// 
        /// Write unknown attribute 
        /// 
        ///  
        /// For template parsing, the 'Set' tag is an unknown tag and contains properties that 
        /// are passed as UnknownAttributes.  Translate these into Property records.
        ///  
        public override void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode)
        {
#if PBTCOMPILER
            bool localAttrib = false; 
            string localTagFullName = string.Empty;
            string localAttribName = xamlUnknownAttributeNode.Name; 
            NamespaceMapEntry[] namespaceMaps = null; 

            if (xamlUnknownAttributeNode.OwnerTypeFullName.Length > 0) 
            {
                // These are attributes on a local tag ...
                localTagFullName = xamlUnknownAttributeNode.OwnerTypeFullName;
                localAttrib = true; 
            }
            else 
            { 
                //  These are attributes on a non-local tag ...
                namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownAttributeNode.XmlNamespace); 
                localAttrib = namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly;
            }

            if (localAttrib) 
            {
                // ... and if there are any periods in the attribute name, then ... 
                int lastIndex = localAttribName.LastIndexOf('.'); 

                if (-1 != lastIndex) 
                {
                    // ... these might be attached props or events defined by a locally defined component,
                    // but being set on this non-local tag.
 
                    string ownerTagName = localAttribName.Substring(0, lastIndex);
 
                    if (namespaceMaps != null) 
                    {
                        if (namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly) 
                        {
                            localTagFullName = namespaceMaps[0].ClrNamespace + "." + ownerTagName;
                        }
                    } 
                    else
                    { 
                        TypeAndSerializer typeAndSerializer = XamlTypeMapper.GetTypeOnly(xamlUnknownAttributeNode.XmlNamespace, 
                                                                                 ownerTagName);
 
                        if (typeAndSerializer != null)
                        {
                            Type ownerTagType = typeAndSerializer.ObjectType;
                            localTagFullName = ownerTagType.FullName; 
                        }
                        else 
                        { 
                            namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownAttributeNode.XmlNamespace);
                            if (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly) 
                            {
                                localTagFullName = namespaceMaps[0].ClrNamespace + "." + ownerTagName;
                            }
                            else 
                            {
                                localTagFullName = string.Empty; 
                            } 
                        }
                    } 

                    localAttribName = localAttribName.Substring(lastIndex + 1);
                }
            } 

            if (localTagFullName.Length == 0 || !IsLocalPass1) 
            { 
#endif
                base.WriteUnknownAttribute(xamlUnknownAttributeNode); 
#if PBTCOMPILER
            }
#endif
        } 

        ///  
        /// WriteEndAttributes occurs after the last attribute (property, complex property or 
        /// def record) is written.  Note that if there are none of the above, then WriteEndAttributes
        /// is not called for a normal start tag. 
        /// 
        public override void WriteEndAttributes(XamlEndAttributesNode xamlEndAttributesNode)
        {
#if PBTCOMPILER 
            // reset the event scope so that a new tag may start a new scope for its own events
            if (_styleModeStack.Mode == StyleMode.VisualTree && !xamlEndAttributesNode.IsCompact) 
            { 
                _isSameScope = false;
            } 
#endif
            if (_styleModeStack.Mode == StyleMode.TriggerBase && !xamlEndAttributesNode.IsCompact)
            {
                MemberInfo dpInfo = null; 
                if (_setterOrTriggerPropertyNode != null)
                { 
                    dpInfo = GetDependencyPropertyInfo(_setterOrTriggerPropertyNode); 
                    base.WriteProperty(_setterOrTriggerPropertyNode);
                    _setterOrTriggerPropertyNode = null; 
                    _setterOrTriggerPropertyMemberInfo = dpInfo;
                }

                _setterTargetNameOrConditionSourceName = null; 

                if (_setterOrTriggerValueNode != null) 
                { 
                    ProcessPropertyValueNode();
                } 
            }

            base.WriteEndAttributes(xamlEndAttributesNode);
 
        }
 
        private MemberInfo GetDependencyPropertyInfo(XamlPropertyNode xamlPropertyNode) 
        {
            string member = xamlPropertyNode.Value; 
            MemberInfo dpInfo = GetCLRPropertyInfo(xamlPropertyNode, ref member);
            if (dpInfo != null)
            {
                // Note: Should we enforce that all DP fields should end with a 
                // "Property" or "PropertyKey" postfix here?
 
                if (BamlRecordWriter != null) 
                {
                    short typeId; 
                    short propertyId = MapTable.GetAttributeOrTypeId(BamlRecordWriter.BinaryWriter,
                                                                     dpInfo.DeclaringType,
                                                                     member,
                                                                     out typeId); 

                    if (propertyId < 0) 
                    { 
                        xamlPropertyNode.ValueId = propertyId;
                        xamlPropertyNode.MemberName = null; 
                    }
                    else
                    {
                        xamlPropertyNode.ValueId = typeId; 
                        xamlPropertyNode.MemberName = member;
                    } 
                } 
            }
 
            return dpInfo;
        }

        private MemberInfo GetCLRPropertyInfo(XamlPropertyNode xamlPropertyNode, ref string member) 
        {
            // Strip off namespace prefix from the event or property name and 
            // map this to an xmlnamespace.  Also extract the class name, if present 
            string prefix = string.Empty;
            string target = member; 
            string propertyName = member;
            int dotIndex = member.LastIndexOf('.');
            if (-1 != dotIndex)
            { 
                target = propertyName.Substring(0, dotIndex);
                member = propertyName.Substring(dotIndex+1); 
            } 
            int colonIndex = target.IndexOf(':');
            if (-1 != colonIndex) 
            {
                // If using .net then match against the class.
                prefix = target.Substring(0, colonIndex);
                if (-1 == dotIndex) 
                {
                    member = target.Substring(colonIndex+1); 
                } 
            }
 
            string xmlNamespace = TokenReader.XmlReader.LookupNamespace(prefix);
            Type targetType = null;

            // Get the type associated with the property or event from the XamlTypeMapper and 
            // use this to resolve the property or event into an EventInfo, PropertyInfo
            // or MethodInfo 
            if (-1 != dotIndex) 
            {
                targetType = XamlTypeMapper.GetTypeFromBaseString(target, ParserContext, false); 
            }
            else if (_setterTargetNameOrConditionSourceName != null)
            {
                targetType = _IDTypes[_setterTargetNameOrConditionSourceName] as Type; 
                if (targetType == null
#if PBTCOMPILER 
                    && !IsLocalPass1 
#endif
                   ) 
                {
                    ThrowException(SRID.TemplateNoTriggerTarget,
                                   _setterTargetNameOrConditionSourceName,
                                   xamlPropertyNode.LineNumber, 
                                   xamlPropertyNode.LinePosition);
 
                } 
            }
            else 
            {
                targetType = TargetType;
            }
 
            MemberInfo memberInfo = null;
            if (targetType != null) 
            { 
                string objectName = propertyName;
                memberInfo = XamlTypeMapper.GetClrInfo( 
                                        false,
                                        targetType,
                                        xmlNamespace,
                                        member, 
                                    ref objectName) as MemberInfo;
            } 
 
            if (memberInfo != null)
            { 
                PropertyInfo pi = memberInfo as PropertyInfo;

                if (pi != null)
                { 
                    // For trigger condition only allow if public or internal getter
                    if (_inSetterDepth < 0 && _styleModeStack.Mode == StyleMode.TriggerBase) 
                    { 
                        if (!XamlTypeMapper.IsAllowedPropertyGet(pi))
                        { 
                            ThrowException(SRID.ParserCantSetTriggerCondition,
                                           pi.Name,
                                           xamlPropertyNode.LineNumber,
                                           xamlPropertyNode.LinePosition); 
                        }
                    } 
                    else // for general Setters check prop setters 
                    {
                        if (!XamlTypeMapper.IsAllowedPropertySet(pi)) 
                        {
                            ThrowException(SRID.ParserCantSetAttribute,
                                           "Property Setter",
                                           pi.Name, 
                                           "set",
                                           xamlPropertyNode.LineNumber, 
                                           xamlPropertyNode.LinePosition); 
                        }
                    } 
                }
            }
            // local properties will be added to the baml in pass2 of the compilation.
            // so don't throw now. 
            else
#if PBTCOMPILER 
                if (!IsLocalPass1) 
#endif
            { 
                if (targetType != null)
                {
                    ThrowException(SRID.TemplateNoProp,
                                   member, 
                                   targetType.FullName,
                                   xamlPropertyNode.LineNumber, 
                                   xamlPropertyNode.LinePosition); 
                }
                else 
                {
                    ThrowException(SRID.TemplateNoTarget,
                                   member,
                                   xamlPropertyNode.LineNumber, 
                                   xamlPropertyNode.LinePosition);
                } 
            } 

            return memberInfo; 
        }

        /// 
        /// The Value="foo" property node for a Setter and a Trigger has been saved 
        /// and is resolved some time afterwards using the associated Property="Bar"
        /// attribute.  This is done so that the property record can be written using 
        /// the type converter associated with "Bar" 
        /// 
        private void ProcessPropertyValueNode() 
        {
            Debug.Assert(_setterOrTriggerValueNode != null);

            if (_setterOrTriggerPropertyMemberInfo != null) 
            {
                // Now we have PropertyInfo or a MethodInfo for the property setter. 
                // Get the type of the property from this which will be used 
                // by BamlRecordWriter.WriteProperty to find an associated
                // TypeConverter to use at runtime. 
                // To allow for per-property type converters we need to extract
                // information from the member info about the property
                Type propertyType = XamlTypeMapper.GetPropertyType(_setterOrTriggerPropertyMemberInfo);
                _setterOrTriggerValueNode.ValuePropertyType = propertyType; 
                _setterOrTriggerValueNode.ValuePropertyMember = _setterOrTriggerPropertyMemberInfo;
                _setterOrTriggerValueNode.ValuePropertyName = XamlTypeMapper.GetPropertyName(_setterOrTriggerPropertyMemberInfo); 
                _setterOrTriggerValueNode.ValueDeclaringType = _setterOrTriggerPropertyMemberInfo.DeclaringType; 

                base.WriteProperty(_setterOrTriggerValueNode); 
            }
            else
            {
                base.WriteBaseProperty(_setterOrTriggerValueNode); 
            }
 
            _setterOrTriggerValueNode = null; 
            _setterOrTriggerPropertyNode = null;
            _setterTargetNameOrConditionSourceName = null; 
            _setterOrTriggerPropertyMemberInfo = null;
        }

        ///  
        /// Write Def Attribute
        ///  
        ///  
        /// Template parsing supports x:ID, so check for this here
        ///  
        public override void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode)
        {
            if (xamlDefAttributeNode.Name == BamlMapTable.NameString)
            { 
                if (BamlRecordWriter != null)
                { 
                    BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); 
                }
            } 
            else
            {
#if PBTCOMPILER
                // Remember that x:Key was read in, since this key has precedence over 
                // the DataType="{x:Type SomeType}" key that may also be present.
                if (xamlDefAttributeNode.Name == XamlReaderHelper.DefinitionName && 
                    _styleModeStack.Mode == StyleMode.Base) 
                {
                    _defNameFound = true; 
                }
#endif
                base.WriteDefAttribute(xamlDefAttributeNode);
            } 
        }
 
#if PBTCOMPILER 
        /// 
        /// Write out a key to a dictionary that has been resolved at compile or parse 
        /// time to a Type object.
        /// 
        public override void WriteDefAttributeKeyType(XamlDefAttributeKeyTypeNode xamlDefNode)
        { 
            // Remember that x:Key was read in, since this key has precedence over
            // the TargetType="{x:Type SomeType}" key that may also be present. 
            if (_styleModeStack.Mode == StyleMode.Base) 
            {
                _defNameFound = true; 
            }
            base.WriteDefAttributeKeyType(xamlDefNode);
        }
#endif 

        ///  
        /// Write Start of an Element, which is a tag of the form / 
        /// 
        ///  
        /// For template parsing, determine when it is withing a Trigger or
        /// MultiTrigger section.  This is done for validity checking of
        /// unknown tags and attributes.
        ///  
        public override void WriteElementStart(XamlElementStartNode xamlElementStartNode)
        { 
            StyleMode mode = _styleModeStack.Mode; 
            bool tagWritten = false;
 
            if (mode == StyleMode.Base && _styleModeStack.Depth == 0)
            {
                // The default TargetType of the Template is needed for resolving names when
                // TargetType is not set. Remember it now appropriately for each kind of Template. 
                // Ideally this should come from an attribute or other means instead of hard-coding here.
                if (KnownTypes.Types[(int)KnownElements.ControlTemplate].IsAssignableFrom(xamlElementStartNode.ElementType)) 
                { 
                    _defaultTargetType = KnownTypes.Types[(int)KnownElements.Control];
                } 
                else if (KnownTypes.Types[(int)KnownElements.DataTemplate].IsAssignableFrom(xamlElementStartNode.ElementType))
                {
                    _defaultTargetType = KnownTypes.Types[(int)KnownElements.ContentPresenter];
#if PBTCOMPILER 
                    // The type to use for the dictionary key depends on what kind of
                    // template this is. Remember it now. 
                    _templateKeyType = KnownTypes.Types[(int)KnownElements.DataTemplateKey]; 
#endif
                } 
                else if (KnownTypes.Types[(int)KnownElements.ItemsPanelTemplate].IsAssignableFrom(xamlElementStartNode.ElementType))
                {
                    _defaultTargetType = KnownTypes.Types[(int)KnownElements.ItemsPresenter];
                } 
            }
 
            _setterOrTriggerPropertyMemberInfo = null; 

            // Track elements during compile so that we can resolve id names to types.  This 
            // is useful when resolving Setter Property / Value attributes.
            _elementTypeStack.Push(xamlElementStartNode.ElementType);

            // Keep style mode and other state up-to-date. 
            CommonElementStartProcessing(xamlElementStartNode, xamlElementStartNode.ElementType, ref mode);
 
            // The very first element encountered within a template block 
            // should a template tree node.
            if (mode == StyleMode.Base && _styleModeStack.Depth > 0) 
            {
                ; // Nothing special to do
            }
            else if (mode == StyleMode.TriggerBase && 
                     (xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.Trigger] ||
                      xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.MultiTrigger] || 
                      xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.DataTrigger] || 
                      xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.MultiDataTrigger] ||
                      xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.EventTrigger])) 
            {
                _inPropertyTriggerDepth = xamlElementStartNode.Depth;
            }
            else if (mode == StyleMode.TriggerBase && 
                     (KnownTypes.Types[(int)KnownElements.SetterBase].IsAssignableFrom(xamlElementStartNode.ElementType)))
            { 
                // Just entered the  section of a Trigger 
                _inSetterDepth = xamlElementStartNode.Depth;
            } 
#if PBTCOMPILER
            else if (_styleModeStack.Mode == StyleMode.DataTypeProperty &&
                     InDeferLoadedSection &&
                     _styleModeStack.Depth >= 2 && 
                     !_defNameFound)
            { 
                // We have to treat DataType="{x:Type SomeType}" as a key in a 
                // resource dictionary, if one is present.  This means generating
                // a series of baml records to use as the key for the defer loaded 
                // body of the Style.
                if (_styleModeStack.Depth == 2)
                {
                    base.WriteKeyElementStart(new XamlElementStartNode( 
                        xamlElementStartNode.LineNumber,
                        xamlElementStartNode.LinePosition, 
                        xamlElementStartNode.Depth, 
                        _templateKeyType.Assembly.FullName,
                        _templateKeyType.FullName, 
                        _templateKeyType,
                        null));
                    base.WriteConstructorParametersStart(new XamlConstructorParametersStartNode(
                        xamlElementStartNode.LineNumber, 
                        xamlElementStartNode.LinePosition,
                        xamlElementStartNode.Depth)); 
                } 
                base.WriteElementStart(xamlElementStartNode);
                tagWritten = true; 
            }
#endif

            // Handle custom serializers within the template section by creating an instance 
            // of that serializer and handing off control.
 
            if (xamlElementStartNode.SerializerType != null && _styleModeStack.Depth > 0) 
            {
                XamlSerializer serializer = XamlTypeMapper.CreateInstance(xamlElementStartNode.SerializerType) 
                                                          as XamlSerializer;
                 if (serializer == null)
                 {
                     ThrowException(SRID.ParserNoSerializer, 
                                   xamlElementStartNode.TypeFullName,
                                   xamlElementStartNode.LineNumber, 
                                   xamlElementStartNode.LinePosition); 
                 }
                 else 
                 {
                     // Depending on whether this is the compile case or the parse xaml
                     // case, we want to convert the xaml into baml or objects.
 
                     #if PBTCOMPILER
                         serializer.ConvertXamlToBaml(TokenReader, 
                                       BamlRecordWriter == null ? ParserContext : BamlRecordWriter.ParserContext, 
                                       xamlElementStartNode, BamlRecordWriter);
                     #else 

                         // If we're in the content of the template, we'll convert to baml.  Then TemplateBamlRecordReader
                         // gets the option of instantiating it or keeping it in baml.  For example, if this is a nested
                         // , it can be instantiated, but if it's a part of the .Resources of an element 
                         // in the template, it needs to be left in baml.
 
                         // Notice that TreeBuilder null check is for the case when the current template is within the 
                         // content section of a parent template. This means we need to be writing to Baml.
                         //  
                         //   
                         //   
                         //     
                         //      
                         //         
                         //              
                         //