private static bool TryGetImageResource(Type owningType, FieldInfo field, ResourceDictionary imageResources, string subPath) { if (string.IsNullOrEmpty(subPath)) { throw new ArgumentNullException("subPath"); } // Get Image attributes object[] attributes = field.GetCustomAttributes(typeof(ImageResourceAttribute), false); if (attributes.Length == 0) { return(false); } var attribute = (ImageResourceAttribute)attributes[0]; Freezable img = null; if (string.IsNullOrEmpty(attribute.ImageName1)) { throw new InvalidOperationException("Cannot have an image attribute whose first image name is null or empty"); } var extension = Path.GetExtension(attribute.ImageName1); if (string.IsNullOrEmpty(extension)) { throw new InvalidOperationException("Cannot have an image attribute whose first image name has no extension"); } extension = extension.ToLower(); // Generate packUri var assmName = owningType.Assembly.GetName(); var basePackUriRel = "/" + assmName + ";component/" + subPath; if (!basePackUriRel.EndsWith("/")) { basePackUriRel += "/"; } if (extension == ".xaml") { var uri = new Uri(basePackUriRel + attribute.ImageName1, UriKind.Relative); img = Application.LoadComponent(uri) as Freezable; if (img == null) { throw new InvalidOperationException("Invalid xaml image resource: " + attribute.ImageName1); } } else if (extension == ".cur") { var uri = new Uri(basePackUriRel + attribute.ImageName1, UriKind.Relative); try { var info = Application.GetResourceStream(uri); img = new FreezableCursor { Cursor = new System.Windows.Input.Cursor(info.Stream) }; } catch (IOException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } else if (extension == ".bmp" || extension == ".png" || extension == ".ico") { // First attempt to retrieve the image as an 'Embedded Resource' (ie legacy WinForms-era resource compilation) var stream = owningType.Assembly.GetManifestResourceStream(owningType + "." + attribute.ImageName1); if (stream != null) { img = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.None); } else { // image must be compiled in as a 'Linked Resource' (ie WPF-era resource compilation) var basePackUriAbs = "pack://application:,,," + basePackUriRel; var uri = new Uri(basePackUriAbs + attribute.ImageName1); try { img = new BitmapImage(uri); } catch (IOException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } } else { throw new Exception( "Unrecognized extension '" + extension + "' on image resource '" + field.Name + "'"); } if (img == null) { throw new Exception("Failed to create image from image resource '" + field.Name + "'"); } // Might it be better to keep the img as a DrawingGroup and then assign to relevant Image type later? if (img is DrawingGroup) { var brush = new DrawingBrush(img as DrawingGroup); brush.Stretch = Stretch.Uniform; img = brush; } if (img.CanFreeze && !img.IsFrozen) { img.Freeze(); } object imageKey = owningType.FullName + "." + attribute.ImageName1; if (field.FieldType.IsAssignableFrom(typeof(ResourceKey))) { var componentResourceKey = new ComponentResourceKey(owningType, imageKey); s_resourceKeys[attribute.ImageName1] = componentResourceKey; imageKey = componentResourceKey; } field.SetValue(owningType, imageKey); if (!imageResources.Contains(imageKey)) { imageResources.Add(imageKey, img); } return(true); }
/// <summary> /// Registers any attributed resource keys found on the type</summary> /// <param name="type">Type, usually a static set of keys</param> /// <param name="resourcePath">Path to resources</param> public static void Register(Type type, string resourcePath) { if (s_registeredTypes.Contains(type)) { return; } s_registeredTypes.Add(type); // Generate packUri AssemblyName assmName = type.Assembly.GetName(); string relativePackUriBase = "/" + assmName.Name + ";component/" + resourcePath; string absolutePackUriBase = "pack://application:,,," + relativePackUriBase; ResourceDictionary imageResources = null; FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo field in fields) { // Get Image attributes object[] attributes = field.GetCustomAttributes(typeof(WpfImageResourceAttribute), false); if (attributes.Length > 0) { if (!field.FieldType.IsAssignableFrom(typeof(ResourceKey))) { System.Diagnostics.Debug.WriteLine("Warning: WpfImageResourceAttribute used on a field which is not a ResourceKey"); } var attribute = (WpfImageResourceAttribute)attributes[0]; Freezable img = null; string extension = System.IO.Path.GetExtension(attribute.ImageName).ToLower(); if (extension == ".bmp" || extension == ".png" || extension == ".ico") { var uri = new Uri(absolutePackUriBase + attribute.ImageName); try { img = new BitmapImage(uri); } catch (IOException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } else if (extension == ".xaml") { var uri = new Uri(relativePackUriBase + attribute.ImageName, UriKind.Relative); img = Application.LoadComponent(uri) as Freezable; if (img == null) { throw new InvalidOperationException("Invalid xaml image resource: " + attribute.ImageName); } } else if (extension == ".cur") { var uri = new Uri(relativePackUriBase + attribute.ImageName, UriKind.Relative); try { var info = Application.GetResourceStream(uri); img = new FreezableCursor { Cursor = new System.Windows.Input.Cursor(info.Stream) }; } catch (IOException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } else { throw new InvalidOperationException("Unrecognized Wpf image resource file extension for file: " + attribute.ImageName); } if (img != null) { // Might it be better to keep the img as a DrawingGroup and then assign to relevant Image type later? if (img is DrawingGroup) { var brush = new DrawingBrush(img as DrawingGroup); brush.Stretch = Stretch.Uniform; img = brush; } if (img.CanFreeze && !img.IsFrozen) { img.Freeze(); } object imageKey = type.FullName + "." + attribute.ImageName; if (field.FieldType.IsAssignableFrom(typeof(ResourceKey))) { imageKey = new ComponentResourceKey(type, imageKey); } field.SetValue(type, imageKey); if (imageResources == null) { imageResources = new ResourceDictionary(); } imageResources.Add(imageKey, img); } } // Get ResourceDictionary attributes if (field.FieldType == typeof(string)) { attributes = field.GetCustomAttributes(typeof(ResourceDictionaryResourceAttribute), false); if (attributes.Length > 0) { var attribute = attributes[0] as ResourceDictionaryResourceAttribute; var dictionary = new ResourceDictionary(); string uri = absolutePackUriBase + attribute.Path; dictionary.Source = new Uri(uri, UriKind.RelativeOrAbsolute); Application.Current.Resources.MergedDictionaries.Add(dictionary); } } } if (imageResources != null) { Application.Current.Resources.MergedDictionaries.Add(imageResources); } }