Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / 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: 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 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