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); }
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)); }
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); }
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); }
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); }
/// <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); }
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); }
/// <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; } })); }
/// <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); } }