How do I construct a pack URI to an image that is in a resource file?
I have an assembly called MyAssembly.Resources.dll
, it has a folder called Images, then in there is a resource file called Assets.resx. This resource file contains my image (called MyImage.png). The line of code I have is:
uri = new Uri("pack://application:,,,/MyAssembly.Resources,Culture=neutral,PublicKeyToken=null;component/Images/Assets/MyImage.png");
However when I try to supply this URI to the constructor of a new BitmapImage I get an IOException with the message
Cannot locate resource 'images/assets/myimage.png'.
Note that I have other loose images in the same assembly which I can retrieve fine using a pack URI, those images have their build action set to Resource but they are not embedded in a resx file. Should I be including the name of the resx file in the path?
(I am looking to embed images in resx files so that I can leverage UI culture settings to retrieve the right image (the image contains text)).
Best Solution
I don't think it's possible using the "pack" protocol scheme. This protocol is related to normalized Open Packaging Conventions specs (http://tools.ietf.org/id/draft-shur-pack-uri-scheme-05.txt for pointers). So the pack uri points to the application package's resources (or parts in OPC terms), not to .NET embedded resources.
However, you can define your own scheme, for example "resx" and use it in WPF component uris. New Uri schemes for such usages can be defined using WebRequest.RegisterPrefix.
Here is an example based on a small Wpf application project named "WpfApplication1". This application has a Resource1.resx file defined (and possibly other localized corresponding Resource1 files, like Resource1.fr-FR.resx for french for example). Each of these ResX files define an Image resource named "img" (note this name is not the same as the image file name the resource is based on).
Here is the MainWindow.xaml:
The uri format is this:
and assembly name is optional, so
is also valid and point to resources in the main assembly (my sample uses this)
This is the code that supports it, in App.xaml.cs or somewhere else, you need to register the new scheme:
And the scheme implementation: