StyleXamlParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Markup / StyleXamlParser.cs / 1 / StyleXamlParser.cs

                            /****************************************************************************\ 
*
* File: StyleXamlParser.cs
*
* Purpose: Class that interfaces with TokenReader and BamlWriter for 
*          parsing Style
* 
* History: 
*    11/13/03:    [....]      Created
* 
* Copyright (C) 2003 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
 
using System.Windows;
using System.Windows.Threading;

#endif 

#if PBTCOMPILER 
namespace MS.Internal.Markup 
#else
namespace System.Windows.Markup 
#endif
{
    /***************************************************************************\
    * 
    * StyleMode
    * 
    * The style parser works in several modes, and tags are interpreted differently 
    * depending on which mode or section of the Style markup that the parser is
    * currently interpreting. 
    *
    \***************************************************************************/

    ///  
    /// Handles overrides for case when Style is being built to a tree
    /// instead of compiling to a file. 
    ///  
    internal class StyleXamlParser : 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 StyleXamlParser(
            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 StyleXamlParser(
            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 style 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 styles. 
                    if (_styleModeStack.Depth == 0) 
                    {
                        done = true;      // Stop the style parse 
                        cleanup = false;  // Don't close the stream
                        TokenReader.ControllingXamlParser = _previousXamlParser;
                    }
                    break; 

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

                // 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 style 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)
        { 
#if PBTCOMPILER
            string localElementFullName = string.Empty; 
            int lastIndex = xamlUnknownTagStartNode.Value.LastIndexOf('.'); 

            // if local complex property bail out now and handle in 2nd pass when TypeInfo 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 == XamlStyleSerializer.VisualTriggersFullPropertyName || 
                    xamlUnknownTagStartNode.Value == XamlStyleSerializer.SettersFullPropertyName)
                { 
                    ThrowException(SRID.StyleKnownTagWrongLocation, 
                                   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); 
#if PBTCOMPILER
            _defNameFound = true;
#endif
            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 style 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 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 
        }

        /// 
        /// Write unknown attribute 
        /// 
        ///  
        /// For style 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 ((_styleModeStack.Mode == StyleMode.Setters || _styleModeStack.Mode == StyleMode.TriggerBase) && 
                !xamlEndAttributesNode.IsCompact)
            { 
                if (_setterOrTriggerValueNode != null) 
                {
                    ProcessPropertyValueNode(); 
                }
#if PBTCOMPILER
                else if (_inEventSetter)
                { 
                    ProcessEventSetterNode(xamlEndAttributesNode);
                } 
#endif 
            }
 
            base.WriteEndAttributes(xamlEndAttributesNode);
        }

        private MemberInfo GetDependencyPropertyInfo(XamlPropertyNode xamlPropertyNode) 
        {
            string member = xamlPropertyNode.Value; 
            MemberInfo dpInfo = GetPropertyOrEventInfo(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 GetPropertyOrEventInfo(XamlNode xamlNode, 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 propOrEvent = member; 
            int dotIndex = member.LastIndexOf('.');
            if (-1 != dotIndex) 
            {
                target = propOrEvent.Substring(0, dotIndex);
                member = propOrEvent.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 (_styleTargetTypeString != null)
            { 
                targetType = XamlTypeMapper.GetTypeFromBaseString(_styleTargetTypeString, ParserContext, false);
                target = _styleTargetTypeString;
            }
            else if (_styleTargetTypeType != null) 
            {
                targetType = _styleTargetTypeType; 
                target = targetType.Name; 
            }
 
            MemberInfo memberInfo = null;
            if (targetType != null)
            {
                string objectName = propOrEvent; 
                memberInfo = XamlTypeMapper.GetClrInfo(
                                        _inEventSetter, 
                                        targetType, 
                                        xmlNamespace,
                                        member, 
                                    ref objectName) as MemberInfo;
            }

            if (memberInfo != null) 
            {
                if (!_inEventSetter) 
                { 
                    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,
                                               xamlNode.LineNumber, 
                                               xamlNode.LinePosition);
                            }
                        }
                        else // for general Setters check prop setters 
                        {
                            if (!XamlTypeMapper.IsAllowedPropertySet(pi)) 
                            { 
                                ThrowException(SRID.ParserCantSetAttribute,
                                               "Property Setter", 
                                               pi.Name,
                                               "set",
                                               xamlNode.LineNumber,
                                               xamlNode.LinePosition); 
                            }
                        } 
                    } 
                }
            } 
            // local properties and events 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.StyleNoPropOrEvent,
                                   (_inEventSetter ? "Event" : "Property"),
                                   member,
                                   targetType.FullName, 
                                   xamlNode.LineNumber,
                                   xamlNode.LinePosition); 
                } 
                else
                { 
                    ThrowException(SRID.StyleNoTarget,
                                   (_inEventSetter ? "Event" : "Property"),
                                   member,
                                   xamlNode.LineNumber, 
                                   xamlNode.LinePosition);
                } 
            } 

            return memberInfo; 
        }

#if PBTCOMPILER
        private void ProcessEventSetterNode(XamlEndAttributesNode xamlEndAttributesNode) 
        {
            // Check for EventSetter properties. These aren't really stored as properties but 
            // resolved at the EventSetter end tag as events by the compiler 
            Debug.Assert(_inEventSetter);
 
            string member = _event;
            MemberInfo memberInfo = GetPropertyOrEventInfo(xamlEndAttributesNode, ref member);
            // If we have an event setter on a locally defined component, write it out
            // as a property instead of an event so that it will be resolved at runtime. 
            if (null != memberInfo)
            { 
                XamlClrEventNode eventNode = new XamlClrEventNode( 
                    xamlEndAttributesNode.LineNumber,
                    xamlEndAttributesNode.LinePosition, 
                    xamlEndAttributesNode.Depth,
                    member,
                    memberInfo,
                    _handler); 
#if HANDLEDEVENTSTOO
                eventNode.HandledEventsToo = _handledEventsToo; 
#endif 
                WriteClrEvent(eventNode);
            } 

            _event = null;
            _handler = null;
#if HANDLEDEVENTSTOO 
            _handledEventsToo = false;
#endif 
        } 
#endif
 
        /// 
        /// 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() 
        {
            if (_setterOrTriggerPropertyInfo != 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(_setterOrTriggerPropertyInfo);
                _setterOrTriggerValueNode.ValuePropertyType = propertyType; 
                _setterOrTriggerValueNode.ValuePropertyMember = _setterOrTriggerPropertyInfo;
                _setterOrTriggerValueNode.ValuePropertyName = XamlTypeMapper.GetPropertyName(_setterOrTriggerPropertyInfo);
                _setterOrTriggerValueNode.ValueDeclaringType = _setterOrTriggerPropertyInfo.DeclaringType;
 
                base.WriteProperty(_setterOrTriggerValueNode);
            } 
            else 
            {
                base.WriteBaseProperty(_setterOrTriggerValueNode); 
            }

            _setterOrTriggerValueNode = null;
            _setterOrTriggerPropertyInfo = null; 
        }
 
        ///  
        /// Write Def Attribute
        ///  
        /// 
        /// Style 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 TargetType="{x:Type SomeType}" key that may also be present.
                if (xamlDefAttributeNode.Name == XamlReaderHelper.DefinitionName && 
                    _styleModeStack.Mode == StyleMode.Base)
                {
                    _defNameFound = true;
                } 
#endif
 
                // Skip Uids for EventSetter, since they are not localizable. 
                if (!_inEventSetter ||
                    xamlDefAttributeNode.Name != XamlReaderHelper.DefinitionUid) 
                {
                    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 style 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; 
            int depth = _styleModeStack.Depth;
            _setterOrTriggerPropertyInfo = null; 
            bool tagWritten = false;

            // The very first element encountered within a style block should be the
            // target type tag, or a Setter. 
            if (mode == StyleMode.Base && depth > 0)
            { 
                if (KnownTypes.Types[(int)KnownElements.SetterBase].IsAssignableFrom(xamlElementStartNode.ElementType)) 
                {
                    if (_setterPropertyEncountered) 
                    {
                        ThrowException(SRID.StyleImpliedAndComplexChildren,
                                   xamlElementStartNode.ElementType.Name,
                                   XamlStyleSerializer.SettersPropertyName, 
                                   xamlElementStartNode.LineNumber,
                                   xamlElementStartNode.LinePosition); 
                    } 
                    mode = StyleMode.Setters;
                    _setterElementEncountered = true; 
                }
                else
                {
                    ThrowException(SRID.StyleNoTopLevelElement, 
                                   xamlElementStartNode.ElementType.Name,
                                   xamlElementStartNode.LineNumber, 
                                   xamlElementStartNode.LinePosition); 
                }
            } 
            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 (mode == StyleMode.TargetTypeProperty &&
                     InDeferLoadedSection && 
                     depth >= 2 &&
                     !_defNameFound)
            {
                // We have to treat TargetType="{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 (depth == 2)
                { 
                    base.WriteKeyElementStart(xamlElementStartNode);
                }
                else
                { 
                    base.WriteElementStart(xamlElementStartNode);
                } 
 
                tagWritten = true;
            } 
#endif

            if (mode == StyleMode.Setters)
            { 
                if (xamlElementStartNode.ElementType == KnownTypes.Types[(int)KnownElements.EventSetter])
                { 
#if !PBTCOMPILER 
                    ThrowException(SRID.StyleNoEventSetters,
                        xamlElementStartNode.LineNumber, 
                        xamlElementStartNode.LinePosition);
#else
                    _inEventSetter = true;
#endif 
                }
                else if ((depth == 2 && _setterElementEncountered) || 
                         (depth == 3 && _setterPropertyEncountered)) 
                {
                    ThrowException(SRID.ParserNoSetterChild, 
                                   xamlElementStartNode.TypeFullName,
                                   xamlElementStartNode.LineNumber,
                                   xamlElementStartNode.LinePosition);
                } 
            }
 
            // Handle custom serializers within the style section by creating an instance 
            // of that serializer and handing off control.
            if (xamlElementStartNode.SerializerType != null && depth > 0) 
            {
                 XamlSerializer serializer;
                 if (xamlElementStartNode.SerializerType == typeof(XamlStyleSerializer))
                 { 
#if PBTCOMPILER
                    // reset the event scope so that any other event setters encountered in this 
                    // style after the nested Style is done parsing will be added to a new scope 
                     _isSameScope = false;
#endif 
                     serializer = new XamlStyleSerializer(ParserHooks);
                 }
                 else if (xamlElementStartNode.SerializerType == typeof(XamlTemplateSerializer))
                 { 
#if PBTCOMPILER
                    // reset the event scope so that any other event setters encountered in this 
                    // style after the nested Template is done parsing will be added to a new scope 
                     _isSameScope = false;
#endif 
                     serializer = new XamlTemplateSerializer(ParserHooks);
                 }
                 else
                 { 
                     serializer = XamlTypeMapper.CreateInstance(xamlElementStartNode.SerializerType) as XamlSerializer;
                 } 
                 if (serializer == null) 
                 {
                     ThrowException(SRID.ParserNoSerializer, 
                                   xamlElementStartNode.TypeFullName,
                                   xamlElementStartNode.LineNumber,
                                   xamlElementStartNode.LinePosition);
                 } 
                 else
                 { 
 
                     // If we're compiling (or otherwise producing baml), convert to baml.
                     // When we don't have a TreeBuilder, we're producing baml. 

#if !PBTCOMPILER

                     if( TreeBuilder == null ) 
                     {
#endif 
                         serializer.ConvertXamlToBaml(TokenReader, 
                                           BamlRecordWriter == null ? ParserContext : BamlRecordWriter.ParserContext,
                                           xamlElementStartNode, BamlRecordWriter); 
#if !PBTCOMPILER
                     }
                     else
                     { 
                         serializer.ConvertXamlToObject(TokenReader, StreamManager,
                                           BamlRecordWriter.ParserContext, xamlElementStartNode, 
                                           TreeBuilder.RecordReader); 
                     }
#endif 

                 }
            }
            else 
            {
                _styleModeStack.Push(mode); 
 
                if (!_inEventSetter)
                { 
#if PBTCOMPILER
                    // If we DO NOT need a dictionary key, then set the flag that says
                    // a key was already found so that one is not manufactured from
                    // the TargetType property. 
                    if (mode == StyleMode.Base && depth == 0)
                    { 
                        _defNameFound = !xamlElementStartNode.NeedsDictionaryKey; 
                    }
#endif 
                    if (!tagWritten)
                    {
                        base.WriteElementStart(xamlElementStartNode);
                    } 
                }
            } 
        } 

        ///  
        /// Write End Element
        /// 
        /// 
        /// For style 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 WriteElementEnd(XamlElementEndNode xamlElementEndNode)
        { 
            StyleMode mode = _styleModeStack.Mode;
            bool tagWritten = false;

            if (mode == StyleMode.TriggerBase && 
                xamlElementEndNode.Depth == _inSetterDepth)
            { 
                // Just exited the  section of a Trigger 
                _inSetterDepth = -1;
            } 

            if (xamlElementEndNode.Depth == _inPropertyTriggerDepth)
            {
                _inPropertyTriggerDepth = -1; 
            }
 
#if PBTCOMPILER 
           if (_styleModeStack.Depth != 1 &&
               mode == StyleMode.TargetTypeProperty && 
               InDeferLoadedSection &&
               !_defNameFound)
            {
                // We have to treat TargetType="{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 in addition to generating the records to set 
                // the TargetType value.
                if (_styleModeStack.Depth == 3) 
                {
                    base.WriteKeyElementEnd(xamlElementEndNode);
                }
                else 
                {
                    base.WriteElementEnd(xamlElementEndNode); 
                } 

                tagWritten = true; 
            }
#endif

            _styleModeStack.Pop(); 

            if (!_inEventSetter) 
            { 
                if (!tagWritten)
                { 
                    base.WriteElementEnd(xamlElementEndNode);
                }
            }
            else if (mode == StyleMode.Setters) 
            {
                _inEventSetter = false; 
            } 
        }
 
#if PBTCOMPILER
        /// 
        /// Write the start of a constructor parameter section
        ///  
        public override void WriteConstructorParameterType(
            XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode) 
        { 
            if (_styleModeStack.Mode == StyleMode.TargetTypeProperty &&
                InDeferLoadedSection && 
                !_defNameFound)
            {
                // Generate a series of baml records to use as the key for the defer loaded
                // body of the Style in addition to generating the records to set 
                // the normal constructor for an element.
                base.WriteConstructorParameterType(xamlConstructorParameterTypeNode); 
            } 
            base.WriteConstructorParameterType(xamlConstructorParameterTypeNode);
        } 
#endif

        /// 
        /// Write the start of a constructor parameter section 
        /// 
        public override void WriteConstructorParametersStart(XamlConstructorParametersStartNode xamlConstructorParametersStartNode) 
        { 
#if PBTCOMPILER
            if (_styleModeStack.Mode == StyleMode.TargetTypeProperty && 
                InDeferLoadedSection &&
                !_defNameFound)
            {
                // We have to treat TargetType="{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 in addition to generating the records to set 
                // the TargetType value.
                base.WriteConstructorParametersStart(xamlConstructorParametersStartNode); 
            }
#endif

            _styleModeStack.Push(); 
            base.WriteConstructorParametersStart(xamlConstructorParametersStartNode);
        } 
 
        /// 
        /// Write the end of a constructor parameter section 
        /// 
        public override void WriteConstructorParametersEnd(XamlConstructorParametersEndNode xamlConstructorParametersEndNode)
        {
#if PBTCOMPILER 
            if (_styleModeStack.Mode == StyleMode.TargetTypeProperty &&
                InDeferLoadedSection && 
                !_defNameFound && 
                _styleModeStack.Depth > 2)
            { 
                // We have to treat TargetType="{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 in addition to generating the records to set 
                // the TargetType value.
                base.WriteConstructorParametersEnd(xamlConstructorParametersEndNode); 
            } 
#endif
 
            base.WriteConstructorParametersEnd(xamlConstructorParametersEndNode);
            _styleModeStack.Pop();
        }
 
        /// 
        /// Write start of a complex property 
        ///  
        /// 
        /// For style parsing, treat complex property tags as 
        /// xml element tags for the purpose of validity checking
        /// 
        public override void WritePropertyComplexStart(XamlPropertyComplexStartNode xamlNode)
        { 
            StyleMode mode = _styleModeStack.Mode;
 
            if (_styleModeStack.Depth == 1) 
            {
                if (xamlNode.PropName == XamlStyleSerializer.TargetTypePropertyName) 
                {
                    mode = StyleMode.TargetTypeProperty;
                }
                else if (xamlNode.PropName == XamlStyleSerializer.BasedOnPropertyName) 
                {
                    mode = StyleMode.BasedOnProperty; 
                } 
                else
                { 
                    ThrowException(SRID.StyleUnknownProp, xamlNode.PropName,
                                   xamlNode.LineNumber, xamlNode.LinePosition);
                }
            } 
            else if (mode == StyleMode.TriggerBase)
            { 
                _visualTriggerComplexPropertyDepth++; 
            }
#if PBTCOMPILER 
            else if (mode == StyleMode.TargetTypeProperty &&
                     InDeferLoadedSection &&
                     !_defNameFound)
            { 
                // We have to treat TargetType="{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 in addition to generating the records to set
                // the TargetType value. 
                base.WritePropertyComplexStart(xamlNode);
            }
#endif
 
            _styleModeStack.Push(mode);
            base.WritePropertyComplexStart(xamlNode); 
        } 

        ///  
        /// Write end of a complex property
        /// 
        /// 
        /// For style parsing, treat complex property tags as 
        /// xml element tags for the purpose of validity checking
        ///  
        public override void WritePropertyComplexEnd(XamlPropertyComplexEndNode xamlNode) 
        {
            if (_styleModeStack.Mode == StyleMode.TriggerBase) 
            {
                _visualTriggerComplexPropertyDepth--;
            }
#if PBTCOMPILER 
            else if (_styleModeStack.Mode == StyleMode.TargetTypeProperty &&
                     InDeferLoadedSection && 
                     !_defNameFound && 
                     _styleModeStack.Depth > 2)
            { 
                // We have to treat TargetType="{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 in addition to generating the records to set 
                // the TargetType value.
                base.WritePropertyComplexEnd(xamlNode); 
            } 
#endif
 
            base.WritePropertyComplexEnd(xamlNode);
            _styleModeStack.Pop();
        }
 
        /// 
        /// Write start of a list complex property 
        ///  
        /// 
        /// For style parsing, treat complex property tags as 
        /// xml element tags for the purpose of validity checking
        /// 
        public override void WritePropertyIListStart(XamlPropertyIListStartNode xamlNode)
        { 
            StyleMode mode = _styleModeStack.Mode;
            int depth = _styleModeStack.Depth; 
 
            if (depth == 1)
            { 
                if (xamlNode.PropName == XamlStyleSerializer.VisualTriggersPropertyName)
                {
                    mode = StyleMode.TriggerBase;
                } 
                else if (xamlNode.PropName == XamlStyleSerializer.SettersPropertyName)
                { 
                    if (_setterElementEncountered) 
                    {
                        ThrowException(SRID.StyleImpliedAndComplexChildren, 
                                   XamlStyleSerializer.SetterTagName,
                                   xamlNode.PropName,
                                   xamlNode.LineNumber, xamlNode.LinePosition);
                    } 
                    mode = StyleMode.Setters;
                    _setterPropertyEncountered = true; 
                } 
                else
                { 
                    ThrowException(SRID.StyleUnknownProp, xamlNode.PropName,
                                   xamlNode.LineNumber, xamlNode.LinePosition);
                }
            } 
            else if ((mode == StyleMode.TriggerBase ||
                      mode == StyleMode.Setters) && 
                     depth == 2) 
            {
                mode = StyleMode.Base; 
            }
            else if (mode == StyleMode.TriggerBase &&
                     depth == 3)
            { 
                if (xamlNode.PropName == XamlStyleSerializer.EventTriggerActions)
                { 
                    mode = StyleMode.TriggerActions; 
                }
            } 

            _styleModeStack.Push(mode);
            base.WritePropertyIListStart(xamlNode);
        } 

        ///  
        /// Write end of a list complex property 
        /// 
        ///  
        /// For style parsing, treat complex property tags as
        /// xml element tags for the purpose of validity checking when we're counting
        /// element tags.
        ///  
        public override void WritePropertyIListEnd(XamlPropertyIListEndNode xamlNode)
        { 
#if PBTCOMPILER 
            if (_styleModeStack.Mode == StyleMode.Setters)
            { 
                _isSameScope = false;
            }
#endif
 
            base.WritePropertyIListEnd(xamlNode);
            _styleModeStack.Pop(); 
        } 

        ///  
        /// Write Property Array Start
        /// 
        public override void WritePropertyArrayStart(XamlPropertyArrayStartNode xamlPropertyArrayStartNode)
        { 
            base.WritePropertyArrayStart(xamlPropertyArrayStartNode);
            _styleModeStack.Push(); 
        } 

 
        /// 
        /// Write Property Array End
        /// 
        public override void WritePropertyArrayEnd(XamlPropertyArrayEndNode xamlPropertyArrayEndNode) 
        {
            base.WritePropertyArrayEnd(xamlPropertyArrayEndNode); 
            _styleModeStack.Pop(); 
        }
 
        /// 
        /// Write Property IDictionary Start
        /// 
        public override void WritePropertyIDictionaryStart(XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode) 
        {
            StyleMode mode = _styleModeStack.Mode; 
            if (_styleModeStack.Depth == 1 && mode == StyleMode.Base) 
            {
                if (xamlPropertyIDictionaryStartNode.PropName == XamlStyleSerializer.ResourcesPropertyName) 
                {
                    mode = StyleMode.Resources;
                }
                else 
                {
                    ThrowException(SRID.StyleUnknownProp, xamlPropertyIDictionaryStartNode.PropName, 
                                   xamlPropertyIDictionaryStartNode.LineNumber, xamlPropertyIDictionaryStartNode.LinePosition); 
                }
            } 

            base.WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode);
            _styleModeStack.Push(mode);
        } 

 
        ///  
        /// Write Property IDictionary End
        ///  
        public override void WritePropertyIDictionaryEnd(XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode)
        {
            base.WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode);
            _styleModeStack.Pop(); 
        }
 
        ///  
        /// Write Text node and do style related error checking
        ///  
        public override void WriteText(XamlTextNode xamlTextNode)
        {
            StyleMode mode = _styleModeStack.Mode;
            // Text is only valid within certain locations in the