I’m writing a modular application using Microsoft Prism and Unity. My application’s Shell project loads various DLLs which all include their own /resources or /images folder and user interface views. Each module, therefore, is a DLL.
When I’m trying to use a resource in my application, it seems I have to be very explicit about its location to make it work. For example, to locate an image in the same module/dll:
<Image Source="pack://application:,,,/MyCompany.MyProduct.MyModule;Component/Images/ZoomIn.gif" />
Do I really have to use the long form version of the URI everytime? I’ve tried shorter versions such as:
pack://application:,,,/Images/ZoomIn.gif
Images/ZoomIn.gif
ZoomIn.gif
etc.
I thought perhaps the 2nd version there should work. When I see Uri examples they often say “relative to the current assembly”. Is this the assembly that is the executable that is running? Or is this the assembly that the code belongs to (my library/module)?
Update:
With Peter Hansen’s help, I was able to shorten it to:
<Image Source="../Images/ZoomOut.png" />
Apparently I had to use the ../ because my view was in a subfolder. I also could leave off the pack:// syntax since the type converter does this for me.
There are a few different options when it comes to retrieving binary resources in WPF, and they all depend on which kind of behavior you want.
If your resources should be embedded inside an assembly, add them to the project in Visual Studio, and set the Build Action to Resource. This way they will be baked into the assembly, and therefore can’t be changed easily.
If they should be left as loose files, add them to the project, and set the Build Action to Content. Also make sure they are being copied to the output directory. This is a good idea, if you need to replace them frequently, and don’t feel like recompiling the assembly every time.
If you want them as loose files, but don’t want to include them in your Visual Studio solution for some reason (maybe they are not known at compiletime), you can access them using the full path or with something called SiteOfOrigin notation. I won’t go into this as that is not relevant in your case.
To access the resources from your code you use a Pack URI, which can have different forms:
pack://application:,,,/img.jpgReferences image in the root of the project.
pack://application:,,,/Folder1/Folder2/img.jpgReferences image in a subfolder of the project.
pack://application:,,,/NameOfDll;Component/img.jpgReferences image in a different assembly to which there is a reference in Visual Studio.
Luckily there is no need to write the full URI when a resource is referenced from XAML.
Basically the
pack://application:,,,part can be avoided, because a TypeConverter exists that can translate part of the location to the full URI for you.For points 1 and 2 above, the same XAML is used to reference the resources, regardless of whether they exist as loose files alongside the assembly at execution time or are embedded inside of it.
The fully defined explicit URI has to be used when referencing the resources from procedural code, though.
I have written some code and included some images, to show how this works.
Relevant XAML:
Relevant code-behind:
Update
When the resource is in the same assembly that is using it, there should be no reason to include the
/NameOfDll;Component/part of the URI. I’m not sure why it’s not working in your case.I have added a Window to Module1, that just references a single image in its own assembly, and that seems to work fine. The Window is shown when a button is clicked in the WPF application.