| File: System\Windows\Markup\XamlStyleSerializer.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // Description: // Class that serializes and deserializes Styles. // using System.Globalization; #if !PBTCOMPILER using System.Windows.Data; #endif #if PBTCOMPILER namespace MS.Internal.Markup #else namespace System.Windows.Markup #endif { /// <summary> /// Class that knows how to serialize and deserialize Style objects /// </summary> internal class XamlStyleSerializer : XamlSerializer { #if PBTCOMPILER #region Construction /// <summary> /// Constructor for XamlStyleSerializer /// </summary> public XamlStyleSerializer() : base() { } internal XamlStyleSerializer(ParserHooks parserHooks) : base() { _parserHooks = parserHooks; } private ParserHooks _parserHooks = null; #endregion Construction /// <summary> /// Convert from Xaml read by a token reader into baml being written /// out by a record writer. The context gives mapping information. /// </summary> internal override void ConvertXamlToBaml ( XamlReaderHelper tokenReader, ParserContext context, XamlNode xamlNode, BamlRecordWriter bamlWriter) { StyleXamlParser styleParser = new StyleXamlParser(tokenReader, context) { BamlRecordWriter = bamlWriter, ParserHooks = _parserHooks }; // Process the xamlNode that is passed in so that the <Style> element is written to baml styleParser.WriteElementStart((XamlElementStartNode)xamlNode); // Parse the entire Style section now, writing everything out directly to BAML. styleParser.Parse(); } #else /// <summary> /// If the Style represented by a group of baml records is stored in a dictionary, this /// method will extract the key used for this dictionary from the passed /// collection of baml records. For Style, this is the type of the first element record /// in the record collection, skipping over the Style element itself. /// </summary> internal override object GetDictionaryKey(BamlRecord startRecord, ParserContext parserContext) { Type styleTargetType = Style.DefaultTargetType; bool styleTargetTypeSet = false; object targetType = null; int numberOfElements = 0; BamlRecord record = startRecord; short ownerTypeId = 0; while (record != null) { if (record.RecordType == BamlRecordType.ElementStart) { BamlElementStartRecord elementStart = record as BamlElementStartRecord; if (++numberOfElements == 1) { // save the type ID of the first element (i.e. <Style>) ownerTypeId = elementStart.TypeId; } else if (numberOfElements == 2) { styleTargetType = parserContext.MapTable.GetTypeFromId(elementStart.TypeId); styleTargetTypeSet = true; break; } } else if (record.RecordType == BamlRecordType.Property && numberOfElements == 1) { // look for the TargetType property on the <Style> element BamlPropertyRecord propertyRecord = record as BamlPropertyRecord; if (parserContext.MapTable.DoesAttributeMatch(propertyRecord.AttributeId, ownerTypeId, TargetTypePropertyName)) { targetType = parserContext.XamlTypeMapper.GetDictionaryKey(propertyRecord.Value, parserContext); } } else if (record.RecordType == BamlRecordType.PropertyComplexStart || record.RecordType == BamlRecordType.PropertyIListStart) { // We didn't find the second element before a complex property like // Style.Triggers, so return the default style target type: FrameworkElement. break; } record = record.Next; } if (targetType == null) { if (!styleTargetTypeSet) { ThrowException(nameof(SR.StyleNoDictionaryKey), parserContext.LineNumber, parserContext.LinePosition); } return styleTargetType; } else return targetType; } // Helper to insert line and position numbers into message, if they are present private void ThrowException( string id, int lineNumber, int linePosition) { string message = SR.GetResourceString(id); XamlParseException parseException; // Throw the appropriate execption. If we have line numbers, then we are // parsing a xaml file, so throw a xaml exception. Otherwise were are // parsing a baml file. if (lineNumber > 0) { message += " "; message += SR.Format(SR.ParserLineAndOffset, lineNumber.ToString(CultureInfo.CurrentCulture), linePosition.ToString(CultureInfo.CurrentCulture)); parseException = new XamlParseException(message, lineNumber, linePosition); } else { parseException = new XamlParseException(message); } throw parseException; } #endif // !PBTCOMPILER #region Data // Constants used for emitting specific properties and attributes for a Style internal const string StyleTagName = "Style"; internal const string TargetTypePropertyName = "TargetType"; internal const string BasedOnPropertyName = "BasedOn"; internal const string VisualTriggersPropertyName = "Triggers"; internal const string ResourcesPropertyName = "Resources"; internal const string SettersPropertyName = "Setters"; internal const string VisualTriggersFullPropertyName = $"{StyleTagName}.{VisualTriggersPropertyName}"; internal const string SettersFullPropertyName = $"{StyleTagName}.{SettersPropertyName}"; internal const string ResourcesFullPropertyName = $"{StyleTagName}.{ResourcesPropertyName}"; internal const string PropertyTriggerPropertyName = "Property"; internal const string PropertyTriggerValuePropertyName = "Value"; internal const string PropertyTriggerSourceName = "SourceName"; internal const string PropertyTriggerEnterActions = "EnterActions"; internal const string PropertyTriggerExitActions = "ExitActions"; internal const string DataTriggerBindingPropertyName = "Binding"; internal const string EventTriggerEventName = "RoutedEvent"; internal const string EventTriggerSourceName = "SourceName"; internal const string EventTriggerActions = "Actions"; internal const string MultiPropertyTriggerConditionsPropertyName = "Conditions"; internal const string SetterTagName = "Setter"; internal const string SetterPropertyAttributeName = "Property"; internal const string SetterValueAttributeName = "Value"; internal const string SetterTargetAttributeName = "TargetName"; internal const string SetterEventAttributeName = "Event"; internal const string SetterHandlerAttributeName = "Handler"; #if HANDLEDEVENTSTOO internal const string SetterHandledEventsTooAttributeName = "HandledEventsToo"; #endif #endregion Data } }