Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Markup / TemplateBamlRecordReader.cs / 1 / TemplateBamlRecordReader.cs
/****************************************************************************\ * * File: TemplateBamlRecordReader.cs * * Purpose: Main class to handle reading a Template Baml records from a stream * * History: * 11/22/04: [....] Created * 06/15/05: [....] Refactor for new template architecture * * Copyright (C) 2004 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.Xml; using System.IO; using System.Windows; using System.Windows.Navigation; using System.Text; using System.Collections; using System.ComponentModel; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media.Animation; using System.Diagnostics; using System.Reflection; using System.Windows.Threading; using System.Windows.Data; using System.Globalization; using MS.Utility; using MS.Internal; namespace System.Windows.Markup { ////// Reads BAML from a Stream that pertains to Template elements and properties. /// This is an internal class /// internal class TemplateBamlRecordReader : BamlRecordReader { #region Constructor ////// TemplateBamlRecordReader constructor /// /// The input BAML stream, if loading from a file /// StartRecord for List of records, if loading from a dictionary /// Index Record into list of records to start parsing at /// The parser context /// Reader stack from upper level parser to get /// context for things such as dictionaries and parents. /// list of root objects for the parse internal TemplateBamlRecordReader( Stream bamlStream, BamlRecord bamlStartRecord, BamlRecord bamlIndexRecord, ParserContext parserContext, ParserStack bamlReaderStack, ArrayList rootList) { Debug.Assert(null != bamlStream || bamlStartRecord != null); Debug.Assert(null != parserContext && null != parserContext.XamlTypeMapper); // Link this baml record reader to the "parent" reader, so that // we can see its context stack. SetPreviousBamlRecordReader( parserContext.BamlReader ); ParserContext = parserContext; RootList = rootList; PreParsedRecordsStart = bamlStartRecord; PreParsedCurrentRecord = bamlIndexRecord; if (bamlStream != null) { BamlStream = bamlStream; } RootElement = ParserContext.RootElement; ComponentConnector = RootElement as IComponentConnector; ContextStack = bamlReaderStack; _elementDepth = 0; // We're starting out in the template element itself, e.g.tag? if( _inTemplateElement ) { // Yes moreData = TryReadTemplateElementRecord( bamlRecord ); // If we're still in the template element itself, ReadRootRecord above is all the processing // we need. if (_inTemplateElement) { return moreData; } // Otherwise, we're on the first child of the root element (the first child of the tag) else { // Put the template's TargetType into the parser context for use by Setter's etc (see comment // on ParserContext.TargetType). ParserContext.TargetType = _frameworkTemplate.TargetTypeInternal; // Give the template its own copy of the parser context. It needs a copy, because it's // going to use it later on every time it's applied. _frameworkTemplate.CopyParserContext(ParserContext); } } // Check to see if we should update _inContent. if (_elementDepth == 1 && CurrentContext.ContextType == ReaderFlags.ClrObject) { // We're directly under the tag ... if (bamlRecord.RecordType == BamlRecordType.ElementStart) { // ... and we're at a start element, so we must be in template content. _inContent = true; _optimizedTemplateContent.BeginReadingContent(ParserContext); } else if( _inContent ) { // ... but we're not on an element start, and we were in content, // so we must not be any more. _inContent = false; _optimizedTemplateContent.EndReadingContent(); } } // Are we in the template content? if( _inContent) { // Yes, we're in template content. We do some minimal amount of // processing here, but mostly pass to AddContentRecord. // If this is a map table record (such as an attribute info), process // it normally. if( BamlRecordHelper.IsMapTableRecordType( bamlRecord.RecordType )) { base.ReadRecord(bamlRecord); } // Simiarly, let base process deferrable content and connection IDs else if( bamlRecord.RecordType == BamlRecordType.DeferableContentStart || bamlRecord.RecordType == BamlRecordType.ConnectionId ) { base.ReadRecord(bamlRecord); } // If this is an element start/end, we have to call the override directly. else if( bamlRecord.RecordType == BamlRecordType.ElementStart ) { // This is to avoid the checks for injected tags done by the base reader ReadElementStartRecord((BamlElementStartRecord)bamlRecord); } else if( bamlRecord.RecordType == BamlRecordType.ElementEnd ) { // This is to avoid the checks for injected tags done by the base reader ReadElementEndRecord(false); } // Otherwise, hand off the record to the OptimizedTemplateContent. else { AddContentRecord( bamlRecord ); } } else { // We're not in the content any more, process the triggers. moreData = ReadNonContentRecord( bamlRecord ); } _currentBamlRecord = null; return _elementDepth > 0 && moreData; } //+----------------------------------------------------------------------- // // ReadRootRecord // // Read a baml record that's part of the template tag itself, i.e. // part of the element. Note that this routine // will keep the _inRootElement flag up-to-date, and will *not* process // the last record, where it discovers that it's out of the root element. // //+----------------------------------------------------------------------- internal bool TryReadTemplateElementRecord( BamlRecord bamlRecord ) { bool moreData = true; Debug.Assert( _inTemplateElement ); if( bamlRecord.RecordType == BamlRecordType.ElementStart ) { // If this is an element start record, we're either on the // tag itself, and not part of the template content (i.e. it's either the // .Resources or the .Triggers). // //+------------------------------------------------------------------------------ internal bool ReadNonContentRecord( BamlRecord bamlRecord ) { bool skipRead = false; // Look for the "Value" and "Property" attributes in triggers, setters, and conditions. // We won't really process these until the end of the element. if (bamlRecord.RecordType == BamlRecordType.Property || bamlRecord.RecordType == BamlRecordType.PropertyWithConverter) { BamlPropertyRecord bamlPropertyRecord = bamlRecord as BamlPropertyRecord; short converterTypeId = 0; BamlPropertyWithConverterRecord bamlPropertyWithConverterRecord = bamlRecord as BamlPropertyWithConverterRecord; if( bamlPropertyWithConverterRecord != null ) { converterTypeId = bamlPropertyWithConverterRecord.ConverterTypeId; } // Is this a "Value" property? If so, see if it's part of a trigger, setter, or // condition, and if so save it away. string name = MapTable.GetAttributeNameFromId(bamlPropertyRecord.AttributeId); if (name == "Value") { if( CurrentContext.ObjectData is Trigger || CurrentContext.ObjectData is DataTrigger ) { Debug.Assert( _triggerValueString == null ); _triggerValueString = bamlPropertyRecord.Value; _triggerValueConverterTypeId = converterTypeId; skipRead = true; } else if( CurrentContext.ObjectData is Setter ) { Debug.Assert( _setterValueString == null ); _setterValueString = bamlPropertyRecord.Value; _setterValueConverterTypeId = converterTypeId; skipRead = true; } else if( CurrentContext.ObjectData is Condition ) { Debug.Assert( _conditionValueString == null ); _conditionValueString = bamlPropertyRecord.Value; _conditionValueConverterTypeId = converterTypeId; skipRead = true; } else { // CurrentContext.ObjectData is none of the // types above, we need skipRead to stay false // so we will ask base BamlRecordReader to process the data. } } else if (name == "Property") { if( CurrentContext.ObjectData is Trigger ) { Debug.Assert( _triggerPropertyString == null ); _triggerPropertyString = bamlPropertyRecord.Value; skipRead = true; } else if( CurrentContext.ObjectData is Setter ) { Debug.Assert( _setterPropertyString == null ); _setterPropertyString = bamlPropertyRecord.Value; skipRead = true; } else if( CurrentContext.ObjectData is Condition ) { Debug.Assert( _conditionPropertyString == null ); _conditionPropertyString = bamlPropertyRecord.Value; skipRead = true; } else { // CurrentContext.ObjectData is none of the // types above, we need skipRead to stay false // so we will ask base BamlRecordReader to process the data. } } else if (name == "SourceName") { if( CurrentContext.ObjectData is Trigger ) { Debug.Assert( _sourceNameString == null ); _sourceNameString = bamlPropertyRecord.Value; skipRead = true; } else if( CurrentContext.ObjectData is Condition ) { Debug.Assert( _sourceNameString == null ); _sourceNameString = bamlPropertyRecord.Value; skipRead = true; } } /* else if( attrInfo.Name == "TargetName" ) { if( CurrentContext.ObjectData is Setter ) { Debug.Assert( _targetNameString == null ); _targetNameString = bamlPropertyRecord.Value; skipRead = true; } } */ } // If this is the end element of a Trigger, Setter, or Condition, // finish processing of it (convert the Value/Property properties). else if (bamlRecord.RecordType == BamlRecordType.ElementEnd) { if (CurrentContext.ObjectData != null) { CompleteSetterOrTriggerOrCondition(CurrentContext.ObjectData); } } // If we didn't process this record internally above, pass it up to base. if (!skipRead) return base.ReadRecord(bamlRecord); else return true; } protected override void ReadPropertyWithExtensionRecord(BamlPropertyWithExtensionRecord bamlPropertyRecord) { string propertyName = MapTable.GetAttributeNameFromId(bamlPropertyRecord.AttributeId); object value = GetExtensionValue(bamlPropertyRecord, propertyName); bool handled = BaseReadOptimizedMarkupExtension(propertyName, value); if (!handled) { base.ReadPropertyWithExtensionRecord(bamlPropertyRecord); } } protected override void ReadPropertyWithStaticResourceIdRecord( BamlPropertyWithStaticResourceIdRecord bamlPropertyWithStaticResourceIdRecord) { string propertyName = MapTable.GetAttributeNameFromId(bamlPropertyWithStaticResourceIdRecord.AttributeId); // Find the StaticResourceValue for the given Id object value = GetStaticResourceFromId(bamlPropertyWithStaticResourceIdRecord.StaticResourceId); bool handled = BaseReadOptimizedMarkupExtension(propertyName, value); if (!handled) { base.ReadPropertyWithStaticResourceIdRecord(bamlPropertyWithStaticResourceIdRecord); } } private bool BaseReadOptimizedMarkupExtension(string propertyName, object value) { object o = CurrentContext.ObjectData; if (propertyName == XamlStyleSerializer.SetterValueAttributeName) { Setter setter = o as Setter; if (setter != null) { Debug.Assert(setter.Value == DependencyProperty.UnsetValue); Debug.Assert(_setterValueObject == DependencyProperty.UnsetValue); _setterValueObject = value; return true; } Trigger trigger = o as Trigger; if (trigger != null) { Debug.Assert(trigger.Value == DependencyProperty.UnsetValue); Debug.Assert(_triggerValueObject == DependencyProperty.UnsetValue); _triggerValueObject = value; return true; } Condition condition = o as Condition; if (condition != null) { Debug.Assert(condition.Value == DependencyProperty.UnsetValue); Debug.Assert(_conditionValueObject == DependencyProperty.UnsetValue); _conditionValueObject = value; return true; } DataTrigger dataTrigger = o as DataTrigger; if (dataTrigger != null) { Debug.Assert(dataTrigger.Value == DependencyProperty.UnsetValue); Debug.Assert(_triggerValueObject == DependencyProperty.UnsetValue); _triggerValueObject = value; return true; } } return false; } protected override void ReadPropertyCustomRecord(BamlPropertyCustomRecord bamlPropertyRecord) { object o = CurrentContext.ObjectData; string propertyName = MapTable.GetAttributeNameFromId(bamlPropertyRecord.AttributeId); if (propertyName == XamlStyleSerializer.SetterPropertyAttributeName) { DependencyProperty propertyDP = GetCustomDependencyPropertyValue(bamlPropertyRecord); Debug.Assert(propertyDP != null); Setter setter = o as Setter; if (setter != null) { Debug.Assert(setter.Property == null); setter.Property = propertyDP; return; } Trigger trigger = o as Trigger; if (trigger != null) { Debug.Assert(trigger.Property == null); trigger.Property = propertyDP; return; } Condition condition = o as Condition; if (condition != null) { Debug.Assert(condition.Property == null); condition.Property = propertyDP; return; } } else if (propertyName == XamlStyleSerializer.SetterValueAttributeName) { Setter setter = o as Setter; if (setter != null) { // Setter "Property" property is always set before "Value" property Debug.Assert(setter.Property != null && setter.Value == DependencyProperty.UnsetValue); setter.Value = GetCustomValue(bamlPropertyRecord, setter.Property.PropertyType, propertyName); return; } Trigger trigger = o as Trigger; if (trigger != null) { // Trigger "Property" property is always set before "Value" property Debug.Assert(trigger.Property != null && trigger.Value == DependencyProperty.UnsetValue); trigger.Value = GetCustomValue(bamlPropertyRecord, trigger.Property.PropertyType, propertyName); return; } Condition condition = o as Condition; if (condition != null) { // Condition "Property" property is always set before "Value" property Debug.Assert(condition.Property != null && condition.Value == DependencyProperty.UnsetValue); condition.Value = GetCustomValue(bamlPropertyRecord, condition.Property.PropertyType, propertyName); return; } } base.ReadPropertyCustomRecord(bamlPropertyRecord); } //+------------------------------------------------------------------------------- // // CompleteSetterOrTriggerOrCondition // // This is called when we found the end tag of a Setter, Trigger, or Condition. // This is where we type-convert the properties that were order-dependent, // e.g. Value property depends on knowing the Property property (so it can find // the right type converter). // //+-------------------------------------------------------------------------------- private void CompleteSetterOrTriggerOrCondition(Object o) { string nameString; object convertedValue = null; DependencyProperty propertyDP = null; // Handle setters Setter setter = o as Setter; if (setter != null) { nameString = setter.TargetName; // do not reset setter.TargetName propertyDP = setter.Property; convertedValue = setter.ValueInternal; CompletePropertyAndValue(o, ref nameString, ref _setterPropertyString, ref _setterValueString, ref _setterValueObject, ref _setterValueConverterTypeId, ref propertyDP, ref convertedValue); setter.Property = propertyDP; setter.Value = convertedValue; return; } // Handle triggers Trigger trigger = o as Trigger; if (trigger != null) { trigger.SourceName = _sourceNameString; propertyDP = trigger.Property; convertedValue = trigger.Value; CompletePropertyAndValue(o, ref _sourceNameString, ref _triggerPropertyString, ref _triggerValueString, ref _triggerValueObject, ref _triggerValueConverterTypeId, ref propertyDP, ref convertedValue ); trigger.Property = propertyDP; trigger.Value = convertedValue; return; } // Handle conditions Condition condition = o as Condition; if (condition != null) { condition.SourceName = _sourceNameString; propertyDP = condition.Property; convertedValue = condition.Value; bool copyDP = true; if (_conditionPropertyString == null && propertyDP == null) { // we get here, for example, in a Condition for a MultiDataTrigger. // This has no Property, but we should still convert the Value // to an object, including resolving MarkupExtensions, freezing, etc. propertyDP = ContentPresenter.ContentProperty; // any DP of type Object will do copyDP = false; } CompletePropertyAndValue(o, ref _sourceNameString, ref _conditionPropertyString, ref _conditionValueString, ref _conditionValueObject, ref _conditionValueConverterTypeId, ref propertyDP, ref convertedValue); if (copyDP) condition.Property = propertyDP; condition.Value = convertedValue; return; } // Handle data triggers DataTrigger dataTrigger = o as DataTrigger; if (dataTrigger != null) { nameString = null; // DataTrigger does not use named elements convertedValue = dataTrigger.Value; propertyDP = ContentPresenter.ContentProperty; // any DP of type Object will do CompletePropertyAndValue(o, ref nameString, ref _triggerPropertyString, ref _triggerValueString, ref _triggerValueObject, ref _triggerValueConverterTypeId, ref propertyDP, ref convertedValue); dataTrigger.Value = convertedValue; return; } } //+------------------------------------------------------------------------- // // CompletePropertyAndValue // // As part of completing the Setter, Trigger, or Condition element, // figure out the property and/or value properties. // //+------------------------------------------------------------------------- private void CompletePropertyAndValue(object targetObject, ref string targetName, ref string propertyString, ref string valueString, ref object valueObject, ref short valueConverterTypeId, ref DependencyProperty propertyDP, ref object convertedValue) { if (propertyDP == null) { if (propertyString == null) { ThrowException(SRID.StylePropertySetterMinAttrs); } // Get the owner type Type ownerType = FindTypeToUseForResolvingProperty( targetName ); // Convert the property string to a DP propertyDP = XamlTypeMapper.ParsePropertyName(ParserContext, propertyString, ref ownerType); if (propertyDP == null) { ThrowException(SRID.ParserNoDPOnOwner, propertyString, ownerType.FullName); } } targetName = null; propertyString = null; // Convert the value string to a value. if (valueString != null) { Debug.Assert(DependencyProperty.UnsetValue == convertedValue); // Yes, convert the value from string TypeConvertContext typeConverterContext = new TypeConvertContext(ParserContext); convertedValue = XamlTypeMapper.ParseProperty( targetObject, propertyDP.PropertyType, propertyDP.Name, propertyDP, typeConverterContext, ParserContext, valueString, valueConverterTypeId); } else if (DependencyProperty.UnsetValue != valueObject) { convertedValue = valueObject; } else if (DependencyProperty.UnsetValue == convertedValue) { ThrowException(SRID.StylePropertySetterMinAttrs); } // Clear all the data holding members valueString = null; valueObject = DependencyProperty.UnsetValue; valueConverterTypeId = 0; // This value will be shared by all instances of the template. So freeze it, // call ME.ProvideValue on it, etc. StyleHelper.ProcessSharedPropertyValue( ParserContext, targetObject, propertyDP, ref convertedValue ); } //+--------------------------------------------------------------------------------- // // FindTypeToUseForResolvingProperty // // When processing the Property property of a Condition/Setter/Trigger, // we need to know the owner type, so that we can look up the property by name. // //+---------------------------------------------------------------------------------- private Type FindTypeToUseForResolvingProperty(string targetName) { // When parsing a CLR property, the type to use is current TypeTag's type, if // there is one, or the type refered to by the Target="SomeID" reference. // The types of the ID reference are held in the _templateNameToType table. Type type = null; // Do we have a target name? if (targetName != null) { // Yes. Get the target's type, which we cached away while reading the content. type = (Type)_templateNameToType[targetName]; if (type == null) { ThrowException(SRID.TemplateNoTarget, targetName); } } // If we don't have an owner type yet, use the one for the // target type of the Template. else { type = _frameworkTemplate.TargetTypeInternal; } return type; } /***************************************************************************\ * * TemplateBamlRecordReader.ReadElementStartRecord * * Read the start of an element. This is used to track element depth, so * this reader knows when to stop reading the template section. * \***************************************************************************/ protected override bool ReadElementStartRecord( BamlElementStartRecord bamlElementStartRecord) { bool usedSerializer = false; _elementDepth++; if( _inContent ) { _lastElementTypeId = bamlElementStartRecord.TypeId; AddContentRecord( bamlElementStartRecord ); } else { usedSerializer = base.ReadElementStartRecord( bamlElementStartRecord ); if( usedSerializer ) { --_elementDepth; } } return usedSerializer; } protected override void ReadConnectionId(BamlConnectionIdRecord bamlConnectionIdRecord) { if( _inContent ) { AddContentRecord( bamlConnectionIdRecord ); } else { base.ReadConnectionId( bamlConnectionIdRecord ); } return; } /****************************************************************************\ * * TemplateBamlRecordReader.ReadElementEndRecord * * Called when parsing the end of an Element. When the end of the Template * is reached, finish parsing the template block by setting the record * collection on the template. * \***************************************************************************/ protected internal override void ReadElementEndRecord(bool fromNestedBamlRecordReader) { // Is this from a nested reader (e.g. a nested style or template)? if( fromNestedBamlRecordReader ) { // If we're in the template content, then do nothing. If we aren't // in the content, then just pass up the call to base. if (!_inContent) { base.ReadElementEndRecord(fromNestedBamlRecordReader); } return; } _elementDepth--; // Are we somewhere other than the end of the template? if( _elementDepth != 0 ) { // If we're in content, just collect the record. if( _inContent ) { AddContentRecord(_currentBamlRecord); } // If we're not in content, process normally else { base.ReadElementEndRecord( fromNestedBamlRecordReader ); } } // Otherwise, we're at the end of the template itself else { // Put the shared Baml content records into the template. // For some reason, setting the ParserContext causes it to update the BamlRecordReader // to point to it. So update that reference here. ParserContext = ParserContext; // We don't need to keep the baml records any more; the template has // kept the ones it needs. _templateNameToType = null; // The template is done parsing, so call back to the base to have the style added // to the parent element, or to a resources dictionary. Check to see if we need // to generate a dictionary key at this point. If it has not been assigned, then // do it now. if (GetDictionaryFromContext(ParentContext, true /*isInjected*/ ) != null && CurrentContext.Key == null) { // We use a DataTemplateKey or TableTemplateKey object as // the key if we have a DataType property set on the template. object key = null; if (_frameworkTemplate != null) { if (_frameworkTemplate.DataTypeInternal != null) { key = new DataTemplateKey(_frameworkTemplate.DataTypeInternal); } } if (key != null) { CurrentContext.Key = key; } } // Process the end record itself PreviousBamlRecordReader.ReadElementEndRecord(true); // Put back the old reader into the ParserContext ParserContext.BamlReader = PreviousBamlRecordReader; } } /****************************************************************************\ * * TemplateBamlRecordReader.ReadDeferableContentStart * * Called when parsing the deferable content start element. * For the case of a ResourceDictionary inside template content, we read * the dictionary values into a byte array while creating the template * content. Later during template instantiation when the dictionary instance * is created we use this buffer to create a memory stream so that the * ResourceDictionary can use it to RealizeDeferredContent. This is required * because at template instantiation time we do not have a stream to work with. * The reader operates on a linked list of BamlRecords instead. * \***************************************************************************/ internal override void ReadDeferableContentStart( BamlDeferableContentStartRecord bamlDeferableContentStartRecord) { if (!_inContent) { base.ReadDeferableContentStart( bamlDeferableContentStartRecord ); return; } AddContentRecord(bamlDeferableContentStartRecord); Stream stream = null; long startPosition = -1; if (PreParsedRecordsStart == null) { stream = BinaryReader.BaseStream; startPosition = stream.Position; } // Read past all the keys and staticresources belonging to this deferred section BamlRecord bamlRecord; BamlRecordType nextType = GetNextRecordType(); while (nextType == BamlRecordType.DefAttributeKeyString || nextType == BamlRecordType.DefAttributeKeyType || nextType == BamlRecordType.KeyElementStart) { bamlRecord = GetNextRecord(); ReadRecord(bamlRecord); if (nextType == BamlRecordType.KeyElementStart) { while (nextType != BamlRecordType.KeyElementEnd) { bamlRecord = GetNextRecord(); ReadRecord(bamlRecord); nextType = bamlRecord.RecordType; } } nextType = GetNextRecordType(); while (nextType == BamlRecordType.StaticResourceStart || nextType == BamlRecordType.StaticResourceId || nextType == BamlRecordType.OptimizedStaticResource) { bamlRecord = GetNextRecord(); ReadRecord(bamlRecord); if (nextType == BamlRecordType.StaticResourceStart) { while (nextType != BamlRecordType.StaticResourceEnd) { bamlRecord = GetNextRecord(); ReadRecord(bamlRecord); nextType = bamlRecord.RecordType; } } nextType = GetNextRecordType(); } nextType = GetNextRecordType(); } if (PreParsedRecordsStart == null) { // Copy the defer load contents into a buffer. long endOfKeysPosition = stream.Position; Int32 valuesSize = (Int32)(bamlDeferableContentStartRecord.ContentSize - endOfKeysPosition + startPosition); byte[] buffer = new byte[valuesSize]; if (valuesSize > 0) { MS.Internal.IO.Packaging.PackagingUtilities.ReliableRead( BinaryReader, buffer, 0, valuesSize); } // Cache the values buffer on the DeferableContentRecord so that it // can then be retrieved and used during template instantiation. bamlDeferableContentStartRecord.ValuesBuffer = buffer; } } #endregion // Overrides /***************************************************************************\ * * AddContentRecord * * Add a new baml record to the collection of records to be held by the * template. * \***************************************************************************/ private void AddContentRecord(BamlRecord bamlRecord ) { // If this is a BamlElementStartRecord, convert it into a // BamlNamedElementStartRecord, as this is what the template // infrastructure is based on. We have to do it here, so that // it is incorporated correctly into the linked list below. bamlRecord = CreateNameRecordIfNecessary( bamlRecord ); // Link the baml records together. We need them linked so that we // can call nested custom serializers, and also for unwinding when we // discover an un-shareable property value. if (_bamlRecordListTail != null ) { _bamlRecordListTail.Next = bamlRecord; } // Pin the record so we can store it on this list. bamlRecord.Pin(); // Also Pin any Debug extension record. BamlRecord debugExtensionRecord=null; if (BamlRecordHelper.HasDebugExtensionRecord(ParserContext.IsDebugBamlStream, bamlRecord)) { debugExtensionRecord = bamlRecord.Next; debugExtensionRecord.Pin(); } // For named elements, keep track of the type of the element. We need this to // resolve property references in triggers. if( bamlRecord.RecordType == BamlRecordType.Property || bamlRecord.RecordType == BamlRecordType.PropertyWithConverter ) { BamlPropertyRecord bamlPropertyRecord = bamlRecord as BamlPropertyRecord; if (MapTable.DoesAttributeMatch(bamlPropertyRecord.AttributeId, BamlAttributeUsage.RuntimeName)) { // (Could search the baml records here instead) _templateNameToType[bamlPropertyRecord.Value] = MapTable.GetTypeFromId( _lastElementTypeId ); } } _optimizedTemplateContent.AddContentRecord( bamlRecord ); // Advance the tail (including any Debug Extension record) _bamlRecordListTail = (debugExtensionRecord == null) ? bamlRecord : debugExtensionRecord; } /****************************************************************************\ * * CreateNameRecordIfNecessary * * This method converts a BamlElementStart record into a * BamlNamedElementStartRecord. See the comment on BamlNamedElementStartRecord * for more detail on that record. * \***************************************************************************/ private BamlRecord CreateNameRecordIfNecessary( BamlRecord bamlRecord ) { // If this isn't a BamlElementStart record, then we don't need to do anything. if( bamlRecord.GetType() != typeof(BamlElementStartRecord) ) { return bamlRecord; } BamlElementStartRecord bamlElementStartRecord = (BamlElementStartRecord)bamlRecord; // Or if it's already a BamlNamedElementStartRecord, then we're similarly done. if( bamlElementStartRecord is BamlNamedElementStartRecord ) { return bamlRecord; } // Convert this BamlElementStartRecord into a BamlNamedElementStartRecord BamlNamedElementStartRecord bamlNamedElementStartRecord = new BamlNamedElementStartRecord(); bamlNamedElementStartRecord.PinnedCount = bamlElementStartRecord.PinnedCount; bamlNamedElementStartRecord.TypeId = bamlElementStartRecord.TypeId; bamlNamedElementStartRecord.Next = bamlElementStartRecord.Next; bamlNamedElementStartRecord.CreateUsingTypeConverter = bamlElementStartRecord.CreateUsingTypeConverter; bamlNamedElementStartRecord.IsInjected = bamlElementStartRecord.IsInjected; bamlElementStartRecord.Next = null; return bamlNamedElementStartRecord; } //+----------------------------------------------------------------------------------------- // // State // //+----------------------------------------------------------------------------------------- short _lastElementTypeId; private int _elementDepth; private FrameworkTemplate _frameworkTemplate; private OptimizedTemplateContent _optimizedTemplateContent; private bool _inTemplateElement; private bool _inContent; private string _triggerValueString; private object _triggerValueObject = DependencyProperty.UnsetValue; private short _triggerValueConverterTypeId; private string _triggerPropertyString; private string _setterValueString; private object _setterValueObject = DependencyProperty.UnsetValue; private short _setterValueConverterTypeId; private string _setterPropertyString; private string _conditionValueString; private object _conditionValueObject = DependencyProperty.UnsetValue; private short _conditionValueConverterTypeId; private string _conditionPropertyString; private string _sourceNameString; private Hashtable _templateNameToType = new Hashtable(); private BamlRecord _bamlRecordListTail; private BamlRecord _currentBamlRecord; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DelegateArgumentValue.cs
- SqlMethodAttribute.cs
- DateTimePicker.cs
- WinInet.cs
- WebServiceFault.cs
- AnnouncementClient.cs
- WebBrowserNavigatingEventHandler.cs
- MimeImporter.cs
- BuildResult.cs
- CodeDomConfigurationHandler.cs
- AttributeProviderAttribute.cs
- DataGridViewRowsAddedEventArgs.cs
- EncryptedReference.cs
- PathSegment.cs
- CompiledRegexRunner.cs
- EncryptedPackage.cs
- ImageMapEventArgs.cs
- VarRemapper.cs
- DrawingAttributeSerializer.cs
- XmlSchemaSimpleContent.cs
- RsaKeyIdentifierClause.cs
- MenuRendererStandards.cs
- SqlWorkflowInstanceStore.cs
- HtmlInputPassword.cs
- ComplexPropertyEntry.cs
- DiscoveryClientChannelFactory.cs
- InstanceLockQueryResult.cs
- ImageListUtils.cs
- LinkArea.cs
- DriveInfo.cs
- RegularExpressionValidator.cs
- CompilerScopeManager.cs
- ShaderEffect.cs
- ReferentialConstraint.cs
- DesignerTransactionCloseEvent.cs
- ContravarianceAdapter.cs
- VirtualDirectoryMapping.cs
- WebPartTracker.cs
- BlockExpression.cs
- SchemaCollectionCompiler.cs
- UInt64.cs
- sapiproxy.cs
- MimeBasePart.cs
- Pair.cs
- AtomServiceDocumentSerializer.cs
- PropertyDescriptorComparer.cs
- ParameterCollectionEditor.cs
- MenuItemAutomationPeer.cs
- GcSettings.cs
- ApplicationFileCodeDomTreeGenerator.cs
- CompilerLocalReference.cs
- SqlProfileProvider.cs
- FlowNode.cs
- MouseEvent.cs
- TextEffect.cs
- GridViewPageEventArgs.cs
- EntityException.cs
- CookielessData.cs
- AnnotationStore.cs
- ComPlusTypeValidator.cs
- embossbitmapeffect.cs
- SymDocumentType.cs
- ResetableIterator.cs
- CompositeFontFamily.cs
- BamlTreeNode.cs
- DataReceivedEventArgs.cs
- Instrumentation.cs
- BitmapDownload.cs
- SqlIdentifier.cs
- InvokeWebService.cs
- CustomValidator.cs
- SecurityPermission.cs
- WindowsListViewGroupSubsetLink.cs
- DataGridClipboardCellContent.cs
- CollectionViewGroup.cs
- GestureRecognizer.cs
- PiiTraceSource.cs
- ToolStripLocationCancelEventArgs.cs
- SchemaNotation.cs
- DomNameTable.cs
- DeflateStream.cs
- Annotation.cs
- Renderer.cs
- SessionStateModule.cs
- XpsS0ValidatingLoader.cs
- ScriptServiceAttribute.cs
- MultipartIdentifier.cs
- Axis.cs
- BrowserCapabilitiesFactoryBase.cs
- SR.cs
- Binding.cs
- ObjectItemCollection.cs
- SvcMapFileLoader.cs
- PrivilegeNotHeldException.cs
- ToolBarButtonClickEvent.cs
- BeginStoryboard.cs
- SBCSCodePageEncoding.cs
- ImageFormatConverter.cs
- GenericTextProperties.cs
- DataExchangeServiceBinder.cs