public override void WriteElementEnd(XamlElementEndNode xamlEndObjectNode) { _compiler.EndElement(_pass2); base.WriteElementEnd(xamlEndObjectNode); }
/// <summary> /// Write end of an unknown tag /// </summary> /// <remarks> /// For template parsing, the 'Set' tag is an unknown tag, but this will map to a /// Trigger set command. Store this as an element end record here. /// </remarks> public override void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode) { if (_inSetterDepth == xamlUnknownTagEndNode.Depth) { XamlElementEndNode elementEnd = new XamlElementEndNode( xamlUnknownTagEndNode.LineNumber, xamlUnknownTagEndNode.LinePosition, xamlUnknownTagEndNode.Depth); base.WriteElementEnd(elementEnd); _inSetterDepth = -1; } else { #if PBTCOMPILER NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownTagEndNode.XmlNamespace); bool localTag = namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly; if (!localTag || !IsLocalPass1) { #endif base.WriteUnknownTagEnd(xamlUnknownTagEndNode); #if PBTCOMPILER } #endif } _styleModeStack.Pop(); }
/// <summary> /// Write End Element /// </summary> /// <remarks> /// For template parsing, determine when it is withing a Trigger or /// MultiTrigger section. This is done for validity checking of /// unknown tags and attributes. /// </remarks> public override void WriteElementEnd(XamlElementEndNode xamlElementEndNode) { bool tagWritten = false; if (_styleModeStack.Mode == StyleMode.TriggerBase && xamlElementEndNode.Depth == _inSetterDepth) { // Just exited the <Setter .../> section of a Trigger _inSetterDepth = -1; } if (xamlElementEndNode.Depth == _inPropertyTriggerDepth) { _inPropertyTriggerDepth = -1; } #if PBTCOMPILER if (_styleModeStack.Mode == StyleMode.DataTypeProperty && InDeferLoadedSection && !_defNameFound) { // We have to treat DataType="{x:Type SomeType}" as a key in a // resource dictionary, if one is present. This means generating // a series of baml records to use as the key for the defer loaded // body of the Style in addition to generating the records to set // the TargetType value. if (_styleModeStack.Depth == 2) { base.WriteElementEnd(xamlElementEndNode); base.WriteConstructorParametersEnd(new XamlConstructorParametersEndNode( xamlElementEndNode.LineNumber, xamlElementEndNode.LinePosition, xamlElementEndNode.Depth)); base.WriteKeyElementEnd(xamlElementEndNode); tagWritten = true; } } #endif // Track elements during compile so that we can resolve names to types. This // is useful when resolving Setter Property / Value. _elementTypeStack.Pop(); _styleModeStack.Pop(); if (!tagWritten) { base.WriteElementEnd(xamlElementEndNode); } }
/// <summary> /// Write End element for a dictionary key section /// </summary> public override void WriteKeyElementEnd( XamlElementEndNode xamlKeyElementEndNode) { _styleModeStack.Pop(); base.WriteKeyElementEnd(xamlKeyElementEndNode); }
/// <summary> /// Write End element for a dictionary key section /// </summary> public virtual void WriteKeyElementEnd( XamlElementEndNode xamlKeyElementEndNode) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteKeyElementEnd(xamlKeyElementEndNode); } }
// Write the end of a def attribute tree section used as the key // in an IDictionary internal void WriteKeyElementEnd( XamlElementEndNode xamlKeyElementEnd) { Debug.Assert(!InStaticResourceSection, "We do not support x:Key within a StaticResource Section"); BamlKeyElementEndRecord endRecord = (BamlKeyElementEndRecord) BamlRecordManager.GetWriteRecord(BamlRecordType.KeyElementEnd); WriteAndReleaseRecord(endRecord, xamlKeyElementEnd); if (_deferLoadingSupport && _deferKeyCollecting) { _deferKeyCollecting = false; _deferElementDepth--; Debug.Assert(_deferElementDepth == 2); } }
// The end of an element has been reached, so write out the end indication internal void WriteElementEnd(XamlElementEndNode xamlElementEndNode) { BamlElementEndRecord bamlElementEnd = (BamlElementEndRecord) BamlRecordManager.GetWriteRecord(BamlRecordType.ElementEnd); // Check if we're queuing up deferable content. If so and we're at the // end tag for that content, now is the time to actually write everything // to the baml stream and rewrite in the file locations for the values // sections. if (_deferLoadingSupport && _deferElementDepth > 0 && _deferElementDepth-- == 1) { WriteDeferableContent(xamlElementEndNode); // Clear all defer related instance data Debug.Assert(_deferElementDepth == 0); Debug.Assert(_deferComplexPropertyDepth == 0); Debug.Assert(_staticResourceElementDepth == 0); Debug.Assert(_dynamicResourceElementDepth == 0); Debug.Assert(_staticResourceRecordList == null); _deferKeys = null; _deferValues = null; _deferElement = null; } else { WriteAndReleaseRecord(bamlElementEnd, xamlElementEndNode); if (_deferLoadingSupport && _staticResourceElementDepth > 0 && _staticResourceElementDepth-- == 1) { // This marks the end of a StaticResource section // Process the StaticResourceRecordList that we // have been gathering this far WriteStaticResource(); // Cleanup the list after processing Debug.Assert(_staticResourceElementDepth == 0); _staticResourceRecordList = null; } else if (_deferLoadingSupport && _dynamicResourceElementDepth > 0 && _dynamicResourceElementDepth-- == 1) { // We have now exited the dynamic resource section } } // we've come to the end of the element. }
// We've reached the end tag of a deferable content section. Write out // the following information, in order: // 1) Start record for deferable content element, and any properties // that are set on that element // 2) All keys for keyed content (if this is a dictionary) // 3) All value sections. If this is a dictionary, then go back // and update the positions in the key records to point to the value // 4) End record for the deferable content element. private void WriteDeferableContent(XamlElementEndNode xamlNode) { // 1) Write Start record and all property information for the start tag for (int h = 0; h<_deferElement.Count; h++) { ValueDeferRecord deferRecord = (ValueDeferRecord)_deferElement[h]; WriteBamlRecord(deferRecord.Record, deferRecord.LineNumber, deferRecord.LinePosition); } // Find where the deferable content starts, which is after the end // of the start tag for the deferable element, and insert a deferable // block start record here. BamlDeferableContentStartRecord bamlDeferableContentStart = (BamlDeferableContentStartRecord)BamlRecordManager.GetWriteRecord(BamlRecordType.DeferableContentStart); WriteBamlRecord(bamlDeferableContentStart, xamlNode.LineNumber, xamlNode.LinePosition); Int64 endOfStart = BinaryWriter.Seek(0, SeekOrigin.Current); // 2) Write key collection for (int i = 0; i<_deferKeys.Count; i++) { KeyDeferRecord keyRecord = (KeyDeferRecord)_deferKeys[i]; // If we don't have a Record stored here, then we didn't find a key // for this dictionary entry. In that case, throw an exception. // Otherwise loop through the records if there is a collection, or // write out the single record if it is a simple key. // NOTE: Make sure to check the List before the individual record because // the list of records takes precedence over a single record. It is // possible for a single record to be stored first, and then later a // Key Element in complex property is found which overrides the // original key value. if (keyRecord.RecordList != null && keyRecord.RecordList.Count > 0) { for (int j = 0; j < keyRecord.RecordList.Count; j++) { ValueDeferRecord keyValueRec = (ValueDeferRecord)keyRecord.RecordList[j]; WriteBamlRecord(keyValueRec.Record, keyValueRec.LineNumber, keyValueRec.LinePosition); } } else { if (keyRecord.Record == null) { XamlParser.ThrowException(SRID.ParserNoDictionaryKey, keyRecord.LineNumber, keyRecord.LinePosition); } else { WriteBamlRecord(keyRecord.Record, keyRecord.LineNumber, keyRecord.LinePosition); } } // Write out the BamlRecords for all the StaticResources belonging to this key List<List<ValueDeferRecord>> staticResourceRecordList = keyRecord.StaticResourceRecordList; if (staticResourceRecordList.Count > 0) { // Iterate through each one of the StaticResources in the list for (int j=0; j<staticResourceRecordList.Count; j++) { // Iterate through each one of the BamlRecords for a StaticResource List<ValueDeferRecord> srRecords = staticResourceRecordList[j]; for (int k=0; k<srRecords.Count; k++) { ValueDeferRecord srRecord = srRecords[k]; WriteBamlRecord(srRecord.Record, srRecord.LineNumber, srRecord.LinePosition); } } } } // 3) Write Value collection, updating each key to point to the value as // it is encountered. Note that the value offsets are relative to the // start of the Values section, not the deferable block as a whole. Int64 endOfKeys = BinaryWriter.Seek(0, SeekOrigin.Current); int keyIndex = 0; for (int j = 0; j<_deferValues.Count; j++) { ValueDeferRecord deferRecord = (ValueDeferRecord)_deferValues[j]; if (deferRecord.UpdateOffset) { KeyDeferRecord deferKeyRecord = (KeyDeferRecord)_deferKeys[keyIndex++]; Int64 position = BinaryWriter.Seek(0, SeekOrigin.Current); IBamlDictionaryKey keyRecord; if (deferKeyRecord.RecordList != null && deferKeyRecord.RecordList.Count > 0) { ValueDeferRecord elementDeferRec = (ValueDeferRecord)(deferKeyRecord.RecordList[0]); keyRecord = (IBamlDictionaryKey)elementDeferRec.Record; } else { keyRecord = (IBamlDictionaryKey)deferKeyRecord.Record; } Debug.Assert(keyRecord != null, "Unknown key record type in defer load dictionary"); if (keyRecord != null) { keyRecord.UpdateValuePosition((Int32)(position-endOfKeys), BinaryWriter); } } WriteBamlRecord(deferRecord.Record, deferRecord.LineNumber, deferRecord.LinePosition); } Debug.Assert(keyIndex == _deferKeys.Count, "Number of keys and values don't match"); // 4) Write end record and update the content size in start record Int64 startOfEnd = BinaryWriter.Seek(0, SeekOrigin.Current); bamlDeferableContentStart.UpdateContentSize((Int32)(startOfEnd - endOfStart), BinaryWriter); BamlElementEndRecord bamlElementEnd = (BamlElementEndRecord)BamlRecordManager.GetWriteRecord(BamlRecordType.ElementEnd); WriteBamlRecord(bamlElementEnd, xamlNode.LineNumber, xamlNode.LinePosition); BamlRecordManager.ReleaseWriteRecord(bamlElementEnd); }
/// <summary> /// Write End Element /// </summary> /// <remarks> /// For style parsing, determine when it is withing a Trigger or /// MultiTrigger section. This is done for validity checking of /// unknown tags and attributes. /// </remarks> public override void WriteElementEnd(XamlElementEndNode xamlElementEndNode) { StyleMode mode = _styleModeStack.Mode; bool tagWritten = false; if (mode == StyleMode.TriggerBase && xamlElementEndNode.Depth == _inSetterDepth) { // Just exited the <Setter .. /> 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; } }