Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / StyleXamlParser.cs / 1305600 / StyleXamlParser.cs
/****************************************************************************\ * * File: StyleXamlParser.cs * * Purpose: Class that interfaces with TokenReader and BamlWriter for * parsing Style * * History: * 11/13/03: peterost 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 thesection 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 thesection 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