C# – Acessing WPF XAML Resources from non-WPF code

c++embedded-resourcewpf

I am currently building an application that consists 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 having is that each component should include an icon and for niceness purposes I defined that as a System.Windows.Media.Brush so I can just use the DrawingBrush exported from Design there. Now I need to access that piece of XAML from non-WPF C# where I currently have the horrible workaround of instantiating the user control and asking it for the resource:

private Brush CachedIcon = null;

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

I couldn't find a way to read that resource (which is a .xaml file, and referenced in a ResourceDictionary in the custom control) from a "normal" C# class. Anything belonging to WPF has that nice TryFindResource method but how to do that otherwise? I don't want to have the XAML file with the icon lying around un-embedded.

Best Solution

In your XAML code make sure the icon resource has the build option set to "Resource", and then reference the resource to make it a xaml static 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 "{xamlName}.g.resource" stream

Example code that loads all icons from a 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);
        }
    }
}