Example #1
0
        public void XmlNamespaceMaps()
        {
            const string xaml =
                @"<Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
   xmlns:test='http://test'
   test:HasAttachableDp.MyDp='Bar'
   Content='{Binding (test:HasAttachableDp.MyProperty), RelativeSource={RelativeSource Self}}' />";
            XamlTypeMapper mapper = new XamlTypeMapper(new string[0], new NamespaceMapEntry[]
            {
                new NamespaceMapEntry
                {
                    XmlNamespace = "http://test",
                    ClrNamespace = "Test.Elements",
                    AssemblyName = "XamlTestClasses"
                }
            });
            ParserContext pc = new ParserContext {
                XamlTypeMapper = mapper
            };
            Window window = (Window)System.Windows.Markup.XamlReader.Parse(xaml, pc);

            window.Show();
            object content = window.Content;

            window.Close();
            Assert.AreEqual("Bar", content);
        }
Example #2
0
        public static ResourceDictionary GetDefaultStyles()
        {
            var resourceKeysType = typeof(ResourceKeys);

            var fieldInfos = resourceKeysType.GetFields();

            var styleFragments = fieldInfos.Select(GenerateDefaultStyleFragment)
                                 .Where(item => item != null);

            var xaml = string.Format(CultureInfo.InvariantCulture, "<ResourceDictionary>\n{0}\n</ResourceDictionary>", string.Join("\n", styleFragments));

            var xamlTypeMapper = new XamlTypeMapper(new string[0]);

            xamlTypeMapper.AddMappingProcessingInstruction("styles", resourceKeysType.Namespace, resourceKeysType.Assembly.FullName);

            var context = new ParserContext {
                XamlTypeMapper = xamlTypeMapper
            };

            context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            context.XmlnsDictionary.Add("styles", "styles");

            var resourceDictionary = (ResourceDictionary)XamlReader.Parse(xaml, context);

            resourceDictionary.Add(_defaultStylesKey, true);

            return(resourceDictionary);
        }
Example #3
0
        public override void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode)
        {
            string localElementFullName = string.Empty;

            NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownTagStartNode.XmlNamespace);

            if (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly)
            {
                string ns = namespaceMaps[0].ClrNamespace;
                if (!string.IsNullOrEmpty(ns))
                {
                    ns += MarkupCompiler.DOT;
                }
                localElementFullName = ns + xamlUnknownTagStartNode.Value;
            }

            if (localElementFullName.Length > 0 && !_pass2)
            {
                // if local complex property bail out now and handle in 2nd pass when TypInfo is available
                int lastIndex = xamlUnknownTagStartNode.Value.LastIndexOf(MarkupCompiler.DOTCHAR);
                if (-1 == lastIndex)
                {
                    _compiler.StartElement(ref _class,
                                           _subClass,
                                           ref _classModifier,
                                           null,
                                           localElementFullName);
                }
            }
            else
            {
                base.WriteUnknownTagStart(xamlUnknownTagStartNode);
            }
        }
Example #4
0
        public static ResourceDictionary GetDefaultStyles()
        {
            var resourceKeysType = typeof(ResourceKeys);

            var baseStyleKeys = resourceKeysType
                                .GetFields()
                                .Where(field => field.GetCustomAttributes <DefaultStyleAttribute>(false).Any());

            var styleFragments = baseStyleKeys.Select(GenerateDefaultStyleFragment).ToList();

            styleFragments.Add("<Style x:Key=\"{x:Static MenuItem.SeparatorStyleKey}\" TargetType=\"Separator\" BasedOn=\"{StaticResource {x:Static styles:ResourceKeys.MenuItemSeparatorStyle}}\" />");

            var xaml = string.Format(CultureInfo.InvariantCulture, "<ResourceDictionary>\n{0}\n</ResourceDictionary>", string.Join("\n", styleFragments));

            var xamlTypeMapper = new XamlTypeMapper(new string[0]);

            xamlTypeMapper.AddMappingProcessingInstruction("styles", resourceKeysType.Namespace ?? string.Empty, resourceKeysType.Assembly.FullName);

            var context = new ParserContext {
                XamlTypeMapper = xamlTypeMapper
            };

            context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            context.XmlnsDictionary.Add("styles", "styles");

            return((ResourceDictionary)XamlReader.Parse(xaml, context));
        }
Example #5
0
        /// <summary>
        /// override for mapping instructions between clr and xml namespaces
        /// </summary>
        public override void WritePIMapping(XamlPIMappingNode xamlPIMappingNode)
        {
            if (!_pass2)
            {
                _compiler.AddUsing(xamlPIMappingNode.ClrNamespace);
            }

            // Local assembly!
            if ((xamlPIMappingNode.AssemblyName == null) || (xamlPIMappingNode.AssemblyName.Length == 0))
            {
                xamlPIMappingNode.AssemblyName = _compiler.AssemblyName;
                bool addMapping = !XamlTypeMapper.PITable.Contains(xamlPIMappingNode.XmlNamespace) ||
                                  ((ClrNamespaceAssemblyPair)XamlTypeMapper.PITable[xamlPIMappingNode.XmlNamespace]).LocalAssembly ||
                                  string.IsNullOrEmpty(((ClrNamespaceAssemblyPair)XamlTypeMapper.PITable[xamlPIMappingNode.XmlNamespace]).AssemblyName);
                if (addMapping)
                {
                    ClrNamespaceAssemblyPair namespaceMapping = new ClrNamespaceAssemblyPair(xamlPIMappingNode.ClrNamespace,
                                                                                             xamlPIMappingNode.AssemblyName);

                    namespaceMapping.LocalAssembly = true;
                    XamlTypeMapper.PITable[xamlPIMappingNode.XmlNamespace] = namespaceMapping;
                    XamlTypeMapper.InvalidateMappingCache(xamlPIMappingNode.XmlNamespace);
                    if (!_pass2 && BamlRecordWriter != null)
                    {
                        BamlRecordWriter = null;
                    }
                }
            }

            base.WritePIMapping(xamlPIMappingNode);
        }
        private static XamlTypeMapper CreateXamlTypeMapper(Type viewModelType, Type viewType)
        {
            var xamlTypeMapper = new XamlTypeMapper(new string[0]);

            xamlTypeMapper.AddMappingProcessingInstruction("vm", viewModelType.Namespace,
                                                           viewModelType.Assembly.GetName().Name);
            xamlTypeMapper.AddMappingProcessingInstruction("v", viewType.Namespace,
                                                           viewType.Assembly.GetName().Name);
            return(xamlTypeMapper);
        }
Example #7
0
        public void TypeMapperWithMappingPI()
        {
            XamlTypeMapper typeMapper = new XamlTypeMapper(new string[0]);

            typeMapper.AddMappingProcessingInstruction("http://elements", "Test.Elements", "XamlTestClasses");
            ParserContext pc = new ParserContext {
                XamlTypeMapper = typeMapper
            };
            object result = System.Windows.Markup.XamlReader.Parse(ElementXaml, pc);

            Assert.IsInstanceOfType(typeof(Element), result);
        }
Example #8
0
        private XamlTypeMapper CreateXamlTypeMapper(Assembly assembly,
                                                    IReadOnlyDictionary <Type, string> typeNamespaceProcessors)
        {
            var xamlTypeMapper = new XamlTypeMapper(new string[0]);

            foreach (var typeKeyValuePair in typeNamespaceProcessors)
            {
                xamlTypeMapper.AddMappingProcessingInstruction(typeKeyValuePair.Value, typeKeyValuePair.Key.Namespace,
                                                               assembly.GetName().Name);
            }

            return(xamlTypeMapper);
        }
Example #9
0
        /// <summary>
        /// Creates the <see cref="DataTemplate"/> with the root node of the specified type.
        /// </summary>
        /// <param name="rootType">The type of the root node of the <see cref="DataTemplate"/> to create.</param>
        /// <returns>The <see cref="DataTemplate"/> with the root node of the <paramref name="rootType"/>.</returns>
        internal static DataTemplate CreateTemplate(Type rootType)
        {
            ParserContext context = new ParserContext();

            XamlTypeMapper mapper = new XamlTypeMapper(Array.Empty <string>());

            mapper.AddMappingProcessingInstruction(XmlNamespace, rootType.Namespace, rootType.Assembly.FullName);

            context.XamlTypeMapper = mapper;

            context.XmlnsDictionary.Add(string.Empty, NamespaceURI);
            context.XmlnsDictionary.Add(XmlNamespace, XmlNamespace);

            return(XamlReader.Parse(string.Format(Template, rootType.Name), context) as DataTemplate);
        }
Example #10
0
        /// <summary>
        /// override for handling a new xmlnamespace Uri
        /// </summary>
        public override void WriteNamespacePrefix(XamlXmlnsPropertyNode xamlXmlnsPropertyNode)
        {
            if (!_pass2)
            {
                List <ClrNamespaceAssemblyPair> cnap = XamlTypeMapper.GetClrNamespacePairFromCache(xamlXmlnsPropertyNode.XmlNamespace);
                if (cnap != null)
                {
                    foreach (ClrNamespaceAssemblyPair u in cnap)
                    {
                        _compiler.AddUsing(u.ClrNamespace);
                    }
                }
            }

            base.WriteNamespacePrefix(xamlXmlnsPropertyNode);
        }
        public void addNamespace <T>(string name)
        {
            const string pattern = @"^\w[\w\d]*$";

            if (!Regex.IsMatch(name, pattern))
            {
                throw new ArgumentException($"Your namespace name is invalid. must match {pattern}. But you did '{name}' wich does not match exactly!");
            }

            var viewType           = typeof(T);
            var namespaceReference = viewType.Namespace ?? String.Empty;
            var assemblyName       = viewType.Assembly.FullName;

            XamlTypeMapper.AddMappingProcessingInstruction(name, namespaceReference, assemblyName);
            XmlnsDictionary.Add(name, name);
        }
Example #12
0
        public void TypeMapperWithNamespaceEntry()
        {
            XamlTypeMapper typeMapper = new XamlTypeMapper(new string[0], new NamespaceMapEntry[] {
                new NamespaceMapEntry("http://elements", "XamlTestClasses", "Test.Elements")
            });
            ParserContext pc = new ParserContext {
                XamlTypeMapper = typeMapper
            };

            object result = System.Windows.Markup.XamlReader.Parse(ElementXaml, pc);

            Assert.IsInstanceOfType(typeof(Element), result);

            MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(ElementXaml));

            result = new System.Windows.Markup.XamlReader().LoadAsync(stream, pc);
            Assert.IsInstanceOfType(typeof(Element), result);
        }
Example #13
0
        public override void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode)
        {
            NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownTagEndNode.XmlNamespace);
            bool localTag = namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly;

            if (localTag && !_pass2)
            {
                // if local complex property bail out now and handle in 2nd pass when TypInfo is available
                int lastIndex = xamlUnknownTagEndNode.LocalName.LastIndexOf(MarkupCompiler.DOTCHAR);
                if (-1 == lastIndex)
                {
                    _compiler.EndElement(_pass2);
                }
            }
            else
            {
                base.WriteUnknownTagEnd(xamlUnknownTagEndNode);
            }
        }
 public XamlNamespace()
 {
     XamlTypeMapper = new XamlTypeMapper(new string[0]);
     XmlnsDictionary.Add(String.Empty, "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
     XmlnsDictionary.Add(X_DEFAILT_NAMESPACE, "http://schemas.microsoft.com/winfx/2006/xaml");
 }
Example #15
0
        /// <summary>
        /// override of GetElementType
        /// </summary>
        public override bool GetElementType(
            XmlReader xmlReader,
            string localName,
            string namespaceUri,
            ref string assemblyName,
            ref string typeFullName,
            ref Type baseType,
            ref Type serializerType)
        {
            if (!ProcessedRootElement &&
                namespaceUri.Equals(XamlReaderHelper.DefinitionNamespaceURI) &&
                (localName.Equals(XamlReaderHelper.DefinitionCodeTag) ||
                 localName.Equals(XamlReaderHelper.DefinitionXDataTag)))
            {
                MarkupCompiler.ThrowCompilerException(SRID.DefinitionTagNotAllowedAtRoot,
                                                      xmlReader.Prefix,
                                                      localName);
            }

            bool foundElement = base.GetElementType(xmlReader, localName, namespaceUri,
                                                    ref assemblyName, ref typeFullName, ref baseType, ref serializerType);

            if (!ProcessedRootElement)
            {
                int count = xmlReader.AttributeCount;

                // save reader's position, to be restored later
                string attrName = (xmlReader.NodeType == XmlNodeType.Attribute) ? xmlReader.Name : null;

                _isRootTag           = true;
                _class               = string.Empty;
                _subClass            = string.Empty;
                ProcessedRootElement = true;
                XamlTypeMapper.IsProtectedAttributeAllowed = false;
                xmlReader.MoveToFirstAttribute();

                while (--count >= 0)
                {
                    string attribNamespaceURI = xmlReader.LookupNamespace(xmlReader.Prefix);

                    if (attribNamespaceURI != null &&
                        attribNamespaceURI.Equals(XamlReaderHelper.DefinitionNamespaceURI))
                    {
                        MarkupCompiler.DefinitionNSPrefix = xmlReader.Prefix;

                        if (xmlReader.LocalName == CLASS)
                        {
                            _class = xmlReader.Value.Trim();
                            if (_class == string.Empty)
                            {
                                // flag an error for processing later in WriteDefAttribute
                                _class = MarkupCompiler.DOT;
                            }
                            else
                            {
                                // flag this so that the Type Mapper can allow protected
                                // attributes on the markup sub-classed root element only.
                                XamlTypeMapper.IsProtectedAttributeAllowed = true;
                            }
                        }
                        else if (xmlReader.LocalName == XamlReaderHelper.DefinitionTypeArgs)
                        {
                            string genericName = _compiler.GetGenericTypeName(localName, xmlReader.Value);

                            foundElement = base.GetElementType(xmlReader, genericName, namespaceUri,
                                                               ref assemblyName, ref typeFullName, ref baseType, ref serializerType);

                            if (!foundElement)
                            {
                                NamespaceMapEntry[] namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(namespaceUri);
                                bool isLocal = namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly;
                                if (!isLocal)
                                {
                                    MarkupCompiler.ThrowCompilerException(SRID.UnknownGenericType,
                                                                          MarkupCompiler.DefinitionNSPrefix,
                                                                          xmlReader.Value,
                                                                          localName);
                                }
                            }
                        }
                        else if (xmlReader.LocalName == SUBCLASS)
                        {
                            _subClass = xmlReader.Value.Trim();
                            if (_subClass == string.Empty)
                            {
                                // flag an error for processing later in WriteDefAttribute
                                _subClass = MarkupCompiler.DOT;
                            }
                            else
                            {
                                _compiler.ValidateFullSubClassName(ref _subClass);
                            }
                        }
                        else if (xmlReader.LocalName == CLASSMODIFIER)
                        {
                            if (!_pass2)
                            {
                                _classModifier = xmlReader.Value.Trim();
                                if (_classModifier == string.Empty)
                                {
                                    // flag an error for processing later in WriteDefAttribute
                                    _classModifier = MarkupCompiler.DOT;
                                }
                            }
                            else
                            {
                                // This direct comparison is ok to do in pass2 as it has already been validated in pass1.
                                // This is to avoid a costly instantiation of the CodeDomProvider in pass2.
                                _isInternalRoot = string.Compare("public", xmlReader.Value.Trim(), StringComparison.OrdinalIgnoreCase) != 0;
                            }
                        }
                    }

                    xmlReader.MoveToNextAttribute();
                }

                if (namespaceUri.Equals(XamlReaderHelper.DefinitionNamespaceURI))
                {
                    xmlReader.MoveToElement();
                }
                else
                {
                    if (attrName == null)
                    {
                        xmlReader.MoveToFirstAttribute();
                    }
                    else
                    {
                        xmlReader.MoveToAttribute(attrName);
                    }
                }
            }
            else if (!_compiler.IsBamlNeeded && !_compiler.ProcessingRootContext && _compiler.IsCompilingEntryPointClass && xmlReader.Depth > 0)
            {
                if ((!localName.Equals(MarkupCompiler.CODETAG) &&
                     !localName.Equals(MarkupCompiler.CODETAG + "Extension")) ||
                    !namespaceUri.Equals(XamlReaderHelper.DefinitionNamespaceURI))
                {
                    _compiler.IsBamlNeeded = true;
                }
            }

            return(foundElement);
        }
Example #16
0
        public override void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode)
        {
            bool   localAttrib      = false;
            string localTagFullName = string.Empty;
            string localAttribName  = xamlUnknownAttributeNode.Name;

            NamespaceMapEntry[] namespaceMaps = null;
            MemberInfo          miKnownEvent  = 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 && !_pass2)
            {
                // ... and if there are any periods in the attribute name, then ...
                int lastIndex = localAttribName.LastIndexOf(MarkupCompiler.DOTCHAR);

                if (-1 != lastIndex)
                {
                    // ... these might be attached props or events defined by a locally defined component,
                    // but being set on this non-local tag.

                    TypeAndSerializer typeAndSerializer = null;
                    string            ownerTagName      = localAttribName.Substring(0, lastIndex);

                    if (namespaceMaps != null)
                    {
                        if (namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly)
                        {
                            // local prop on a known tag
                            localTagFullName = namespaceMaps[0].ClrNamespace + MarkupCompiler.DOT + ownerTagName;
                        }
                    }
                    else
                    {
                        typeAndSerializer = XamlTypeMapper.GetTypeOnly(xamlUnknownAttributeNode.XmlNamespace,
                                                                       ownerTagName);

                        if (typeAndSerializer != null)
                        {
                            // known local attribute on a local tag

                            Type ownerTagType = typeAndSerializer.ObjectType;
                            localTagFullName = ownerTagType.FullName;
                            localAttribName  = localAttribName.Substring(lastIndex + 1);

                            // See if attached event first
                            miKnownEvent = ownerTagType.GetMethod(MarkupCompiler.ADD + localAttribName + MarkupCompiler.HANDLER,
                                                                  BindingFlags.Public | BindingFlags.Static |
                                                                  BindingFlags.FlattenHierarchy);

                            if (miKnownEvent == null)
                            {
                                // Not an attached event, so try for a clr event.
                                miKnownEvent = ownerTagType.GetEvent(localAttribName,
                                                                     BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                            }

                            if (miKnownEvent != null)
                            {
                                if (_events == null)
                                {
                                    _events = new ArrayList();
                                }

                                _events.Add(new MarkupCompiler.MarkupEventInfo(xamlUnknownAttributeNode.Value,
                                                                               localAttribName,
                                                                               miKnownEvent,
                                                                               xamlUnknownAttributeNode.LineNumber));

                                WriteConnectionId();
                            }
                        }
                        else
                        {
                            namespaceMaps = XamlTypeMapper.GetNamespaceMapEntries(xamlUnknownAttributeNode.XmlNamespace);
                            if (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly)
                            {
                                // local prop on local tag
                                localTagFullName = namespaceMaps[0].ClrNamespace + MarkupCompiler.DOT + ownerTagName;
                            }
                            else
                            {
                                // unknown prop on local tag -- Error!
                                localTagFullName = string.Empty;
                            }
                        }
                    }

                    if (typeAndSerializer == null)
                    {
                        localAttribName = localAttribName.Substring(lastIndex + 1);
                    }
                }
                // else if it is an unknown non-attached prop on a non-local tag -- instant error!
            }

            if (localTagFullName.Length > 0 && !_pass2)
            {
                if (xamlUnknownAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName)
                {
                    string attributeValue = xamlUnknownAttributeNode.Value;

                    Debug.Assert(_name == null && _nameField == null, "Name has already been set");
                    _nameField = _compiler.AddNameField(attributeValue, xamlUnknownAttributeNode.LineNumber, xamlUnknownAttributeNode.LinePosition);
                    _name      = attributeValue;

                    if (_nameField != null)
                    {
                        WriteConnectionId();
                    }
                }
                else if (localAttribName.Equals(STARTUPURI) &&
                         _compiler.IsCompilingEntryPointClass)
                {
                    // if Application.StartuoUri property then don't bamlize, but gen code since
                    // this is better for perf as Application is not a DO.
                    PropertyInfo pi = KnownTypes.Types[(int)KnownElements.Application].GetProperty(localAttribName);
                    _compiler.AddApplicationProperty(pi,
                                                     xamlUnknownAttributeNode.Value,
                                                     xamlUnknownAttributeNode.LineNumber);
                    return;
                }
                else if (miKnownEvent == null)
                {
                    // This may or may not be a local event, but there is no way to know in Pass1.
                    // So we prepare for the worst case sceanrio and assume it may be one so that
                    // the Xaml compiler can generate the CreateDelegate code.
                    _compiler.HasLocalEvent = true;
                }
            }
            else
            {
                base.WriteUnknownAttribute(xamlUnknownAttributeNode);
            }

            _compiler.IsBamlNeeded = true;
        }
Example #17
0
        /// <summary>
        /// Finds the <see cref="FrameworkElement"/> a specific style is based on.
        /// </summary>
        /// <param name="resourceDictionaryUri">The resource dictionary URI.</param>
        /// <param name="styleKey">The style key.</param>
        /// <returns>
        /// <see cref="Type"/> or <c>null</c> if the style is not based on a <see cref="FrameworkElement"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">The <paramref name="resourceDictionaryUri"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="styleKey"/> is <c>null</c>.</exception>
        /// <remarks>
        /// This method is introduced due to the lack of the ability to use DynamicResource for the BasedOn property when
        /// defining styles inside a derived theme.
        /// Should be used in combination with the <see cref="RecreateDefaultStylesBasedOnTheme"/> method.
        /// </remarks>
        private static Type FindFrameworkElementStyleIsBasedOn(Uri resourceDictionaryUri, string styleKey)
        {
            Argument.IsNotNull("resourceDictionaryUri", resourceDictionaryUri);
            Argument.IsNotNull("styleKey", styleKey);

            if (_styleToFrameworkElementTypeCache.ContainsKey(styleKey))
            {
                return(_styleToFrameworkElementTypeCache[styleKey]);
            }

            try
            {
                XmlDocument doc;

                if (_resourceDictionaryCache.ContainsKey(resourceDictionaryUri))
                {
                    doc = _resourceDictionaryCache[resourceDictionaryUri];
                }
                else
                {
                    StreamResourceInfo streamResourceInfo = Application.GetResourceStream(resourceDictionaryUri);
                    var reader = new XmlBamlReader(streamResourceInfo.Stream);

                    doc = new XmlDocument();
                    doc.Load(reader);

                    _resourceDictionaryCache.Add(resourceDictionaryUri, doc);
                }

                #region Create xml namespace manager
                // Create namespace manager (all namespaces are required)
                var xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
                foreach (XmlAttribute namespaceAttribute in doc.DocumentElement.Attributes)
                {
                    // Clean up namespace (remove xmlns prefix)
                    string xmlNamespace = namespaceAttribute.Name.Replace("xmlns", "").TrimStart(new char[] { ':' });
                    xmlNamespaceManager.AddNamespace(xmlNamespace, namespaceAttribute.Value);
                }

                // Add a dummy node
                xmlNamespaceManager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                xmlNamespaceManager.AddNamespace("ctl", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                #endregion

                string xpath        = string.Format("/ctl:ResourceDictionary/ctl:Style[@x:Key='{0}']/@BasedOn", styleKey);
                var    xmlAttribute = doc.SelectSingleNode(xpath, xmlNamespaceManager) as XmlAttribute;
                if (xmlAttribute == null)
                {
                    Log.Warning("Style '{0}' does not have the 'BasedOn' attribute defined", styleKey);

                    _styleToFrameworkElementTypeCache.Add(styleKey, null);

                    return(null);
                }

                string basedOnValue = xmlAttribute.Value;
                basedOnValue = basedOnValue.Replace("StaticResource", "");
                basedOnValue = basedOnValue.Replace("x:Type", "").Trim(new[] { ' ', '{', '}' });

                #region Create xml type mapper
                var xamlTypeMapper = new XamlTypeMapper(new[] { "PresentationFramework" });
                foreach (XmlAttribute namespaceAttribute in doc.DocumentElement.Attributes)
                {
                    string xmlNamespace = namespaceAttribute.Name.Replace("xmlns", "").TrimStart(new char[] { ':' });

                    string value        = namespaceAttribute.Value;
                    string clrNamespace = value;
                    string assemblyName = string.Empty;

                    if (clrNamespace.StartsWith("clr-namespace:"))
                    {
                        // We have a hit (formatting is normally one of the 2 below):
                        // * clr-namespace:[NAMESPACE]
                        // * clr-namespace:[NAMESPACE];assembly=[ASSEMBLY]
                        if (clrNamespace.Contains(";"))
                        {
                            clrNamespace = clrNamespace.Split(new char[] { ';' })[0];
                        }
                        clrNamespace = clrNamespace.Replace("clr-namespace:", "");

                        if (value.Contains(";"))
                        {
                            assemblyName = value.Split(new char[] { ';' })[1].Replace("assembly:", "");
                        }

                        xamlTypeMapper.AddMappingProcessingInstruction(xmlNamespace, clrNamespace, assemblyName);
                    }
                }
                #endregion

                string[] splittedType  = basedOnValue.Split(new[] { ':' });
                string   typeNamespace = (splittedType.Length == 2) ? splittedType[0] : "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
                string   typeName      = (splittedType.Length == 2) ? splittedType[1] : splittedType[0];
                var      type          = xamlTypeMapper.GetType(typeNamespace, typeName);
                if (type == null)
                {
                    _styleToFrameworkElementTypeCache.Add(styleKey, null);
                    return(null);
                }

                Log.Debug("Style '{0}' is based on type '{1}'", styleKey, type);

                if ((type == typeof(FrameworkElement)) || type.IsSubclassOf(typeof(FrameworkElement)))
                {
                    _styleToFrameworkElementTypeCache.Add(styleKey, type);
                    return(type);
                }


                _styleToFrameworkElementTypeCache.Add(styleKey, null);
                return(null);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to find the framework element where style '{0}' is based on", styleKey);
                return(null);
            }
        }
Example #18
0
        /// <summary>
        /// Finds the <see cref="FrameworkElement"/> a specific style is based on.
        /// </summary>
        /// <param name="resourceDictionaryUri">The resource dictionary URI.</param>
        /// <param name="styleKey">The style key.</param>
        /// <returns>
        /// <see cref="Type"/> or <c>null</c> if the style is not based on a <see cref="FrameworkElement"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">The <paramref name="resourceDictionaryUri"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="styleKey"/> is <c>null</c>.</exception>
        /// <remarks>
        /// This method is introduced due to the lack of the ability to use DynamicResource for the BasedOn property when
        /// defining styles inside a derived theme.
        /// Should be used in combination with the <see cref="RecreateDefaultStylesBasedOnTheme"/> method.
        /// </remarks>
        private static Type FindFrameworkElementStyleIsBasedOn(Uri resourceDictionaryUri, string styleKey)
        {
            Argument.IsNotNull("resourceDictionaryUri", resourceDictionaryUri);
            Argument.IsNotNull("styleKey", styleKey);

            return(_styleToFrameworkElementTypeCache.GetFromCacheOrFetch(styleKey, () =>
            {
                try
                {
                    var xmlDocInfo = GetResourceXmlDocument(resourceDictionaryUri);
                    var doc = xmlDocInfo.Item1;
                    var xmlNamespaceManager = xmlDocInfo.Item2;

                    var xpath = string.Format("/ctl:ResourceDictionary/ctl:Style[@x:Key='{0}']/@BasedOn", styleKey);
                    var xmlAttribute = doc.SelectSingleNode(xpath, xmlNamespaceManager) as XmlAttribute;
                    if (xmlAttribute == null)
                    {
                        Log.Warning("Style '{0}' does not have the 'BasedOn' attribute defined", styleKey);
                        return null;
                    }

                    var basedOnValue = xmlAttribute.Value;
                    basedOnValue = basedOnValue.Replace("StaticResource", string.Empty);
                    basedOnValue = basedOnValue.Replace("x:Type", string.Empty).Trim(' ', '{', '}');

                    #region Create xml type mapper
                    var xamlTypeMapper = new XamlTypeMapper(new[] { "PresentationFramework" });
                    foreach (XmlAttribute namespaceAttribute in doc.DocumentElement.Attributes)
                    {
                        var xmlNamespace = namespaceAttribute.Name.Replace("xmlns", string.Empty).TrimStart(':');

                        var value = namespaceAttribute.Value;
                        var clrNamespace = value;
                        var assemblyName = string.Empty;

                        if (clrNamespace.StartsWith("clr-namespace:"))
                        {
                            // We have a hit (formatting is normally one of the 2 below):
                            // * clr-namespace:[NAMESPACE]
                            // * clr-namespace:[NAMESPACE];assembly=[ASSEMBLY]
                            if (clrNamespace.Contains(";"))
                            {
                                clrNamespace = clrNamespace.Split(';')[0];
                            }
                            clrNamespace = clrNamespace.Replace("clr-namespace:", string.Empty);

                            if (value.Contains(";"))
                            {
                                assemblyName = value.Split(';')[1].Replace("assembly:", string.Empty);
                            }

                            xamlTypeMapper.AddMappingProcessingInstruction(xmlNamespace, clrNamespace, assemblyName);
                        }
                    }
                    #endregion

                    var splittedType = basedOnValue.Split(':');
                    var typeNamespace = (splittedType.Length == 2) ? splittedType[0] : "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
                    var typeName = (splittedType.Length == 2) ? splittedType[1] : splittedType[0];
                    var type = xamlTypeMapper.GetType(typeNamespace, typeName);
                    if (type == null)
                    {
                        return null;
                    }

                    Log.Debug("Style '{0}' is based on type '{1}'", styleKey, type);

                    if ((type == typeof(FrameworkElement)) || type.IsSubclassOf(typeof(FrameworkElement)))
                    {
                        return type;
                    }

                    return null;
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Failed to find the framework element where style '{0}' is based on", styleKey);
                    return null;
                }
            }));
        }