Recognizing WPF XAML Resources from Non-WPF Code

I am currently creating an application consisting of several components, each of which is essentially a WPF user control with a little C # code around it for the plugin system to work (using MEF).

The problem I am facing is that each component must contain an icon and for convenience, I have defined it as System.Windows.Media.Brush , so I can just use the DrawingBrush exported from Design there. Now I need to access this part of XAML from non-WPF C #, where I have a terrible workaround for creating a user control and requesting it for a resource:

 private Brush CachedIcon = null; public override Brush Icon { get { if (CachedIcon == null) { CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon")); } return CachedIcon; } } 

I could not find a way to read this resource (which is a .xaml file and specified in a ResourceDictionary in a user control) from a regular C # class. Everything that belongs to WPF has a good TryFindResource method, but how to do it otherwise? I do not want the XAML file with the icon to lie around the non-built.

+7
c # wpf embedded-resource
source share
4 answers

In the XAML code, verify that the icon resource has an assembly parameter set to "Resource" and then refers to the resource to make it a static xaml resource

 <UserControl.Resources> <BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" /> </UserControl.Resources> 

Then, in your .Net 2.0 code, you will find the resource in the stream "{xamlName} .g.resource

Sample code that loads all the icons from the xaml dll into a dictionary:

 using System.IO; using System.Reflection; using System.Collections; using System.Resources; ... var icons = new Dictionary<String, Bitmap>(); var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll")); Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources"); using (ResourceReader resourceReader = new ResourceReader(resourceStream)) { foreach (DictionaryEntry resourceEntry in resourceReader) { if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) { icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap); } } } 
+2
source share

My suggestions:

  • Provide metadata in your control about where the icon can be found. You can do this with your own attribute (see Example 1 below). This metadata allows you to load the icon without instantiating the control.

  • Since you use MEF, you can use metadata in your export to achieve the same as above. More details here . See Example 2. below.

  • ImageSource your icon as an ImageSource , not a Brush . You can use the WPF Image control to display your ImageSource , or you can draw it using ImageBrush .

  • Use the technique provided by TFD to read the resource with the name specified in the metadata. Unfortunately, WPF does not seem to provide anything like BamlReader , which will greatly simplify loading a WPF resource from a context other than WPF.

Example 1:

 [Icon("MyIconResourceName")] public class BlahControl : Control { ... } 

Example 2:

 [Export(typeof(IApplicationComponent))] [ExportMetadata("IconResource", "MyIconResourceName")] public class BlahControl : Control { ... } 
+1
source share

You can read resources from your assembly as a stream.

Sample code here: http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html

0
source share

Define the icons at the application level, not in the control or in the xaml file of the application file. Then you can use the same TryFindResource method, but without instantiating the control.

0
source share

All Articles