Loading images in WPF from code - c#

I must have read tons of solutions online, but for some idiotic reason I can not get them to work.
I have a .jpg image in the Resources folder of my project, and the image is set to Build Action: Resource (not embedded resource) and never copy to output folder.
My image is not added to my resources.resx file.
I am trying to access the file like so:
lResult = new BitmapImage(new Uri(#"pack://application:,,,/Resources/ImageMissing.jpg", UriKind.Absolute));
But this fails saying that there is no image there.
This is so basic I feel really stupid, but I just cannot seem to grasp the simple concept of resources usage.
Thank you.

If you need to specify that the resource being referred to is referenced from the local assembly, then I would think that you would want to include "component". For example, I have some code that loads an icon from a resource available from the same assembly in which my code resides. I write this:
var SourceUri = new Uri("pack://application:,,,/MyCompany.MyProduct.MyAssembly;component/MyIcon.ico", UriKind.Absolute);
thisIcon = new BitmapImage(SourceUri);
As noted in the article available at http://msdn.microsoft.com/en-us/library/aa970069.aspx, the following additional examples illustrate the use of "component":
The following example shows the pack URI for a XAML resource file that is located in the root of the referenced assembly's project folder.
pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that is located in a subfolder of the referenced assembly's project folder.
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that is located in the root folder of a referenced, version-specific assembly's project folder.
pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml
Note that the pack URI syntax for referenced assembly resource files can be used only with the application:/// authority. For example, the following is not supported in WPF.
pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml

You need one more comma in there. Here is the documentation on Pack URIs in WPF. Notice there are three commas when using the authority.
lResult = new BitmapImage(new Uri(#"pack://application:,,,/Resources/ImageMissing.jpg", UriKind.Absolute));

Did you happen to rename the file (or folder) in the Solution Explorer and then not clean or rebuild the application?
If you're positive the name in your URI matches what is in the Solution Explorer, then try right clicking the solution and selecting "Rebuild".

The problem is the image has not been added to your project - including it in the resources file is not enough.
Right click your project > Add Existing Item > Browse to and find and add the image.
Then all you need to do is:
myImage = new BitmapImage(new Uri(#"ImageMissing.jpg", UriKind.RelativeOrAbsolute));

You probably created this second library as "Class Library" instead "WPF Custom Library". Creating xaml files or embedding images as "Resources" in a class library is not enough for WPF, you are probably missing the following in your AssemblyInfo.cs file:
Properties/AssemblyInfo.cs
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

Try this:
var icon = BitmapFrame.Create(Application.GetResourceStream(
new Uri("MyAppBitmap.jpg", UriKind.RelativeOrAbsolute)).Stream);

Related

WPF accessing a resource from anywhere in the assembly using relative path

In my application I am creating a ton of custom controls that I'm then using in different windows. The structure of my project looks something like this:
Controls (folder)
MemberList (class)
Resources (folder)
Windows (folder)
Window1.xaml
Window2.xaml
Helper windows (folder)
Window3.xaml
I am creating classes (controls) that I store in the Controls folder. If I want to use an image in the control, I access it like so:
new Uri("../Resources/my_image.png", UriKind.Relative)
Sometimes though, I want to use the same control in multiple windows and sometimes these windows are stored in different folders. If I use the control in say Window3 that is stored in another folder, the image is not displayed.
If I change the Uri to this: (adding another "go back" command in the path)
new Uri("../../Resources/my_image.png", UriKind.Relative)
the image is being displayed in the Window3, but it is not displayed in the Window1 or Window2.
Is there a way to create paths that are relative to the main executable and not relative to the window that is displaying the control?
EDIT:
I forgot to mention one important part. Because of the fact that while starting this application I was just learning how to use WPF, I messed one thing. My resources folder is not in the folder that contains the main executable.
My file structure looks like this:
bin
Debug
MyApplication.exe
Resources
I was trying to use the path that everyone suggested:
new Uri("pack://application:,,,/../../my_image.png", UriKind.RelativeOrAbsolute)
but I get the exception:
Cannot locate resource 'my_image.png'.
I could try to relocate the Resources folder, but it would mess up all other paths. Is there any way to go "back" in folder structure in the "pack" uri? If not, what would be the best way to relocate a folder so all paths do not get messed up?
Use a "pack" uri...so you would use:
pack://application:,,,/Resources/my_image.png
so like this:
new Uri("pack://application:,,,/Resources/my_image.png");
to refer to your "image" from ANY of your Windows/Controls.
If you will have other "projects"/"assemblies"...which you want to be able to refer to the resource then use:
pack://application:,,,/AssemblyNameContainingResource;component/Resources/my_image.png
And when you are adding your images in your Resource folder....make sure you use Resource as the Build Action.
Use Pack Uri Scheme
Resource File Pack URIs - Local Assembly
The pack URI for a resource file that is compiled into the local
assembly uses the following authority and path:
Authority: application:///.
Path: The name of the resource file, including its path relative to the root of the local assembly project folder.
The following example shows the pack URI for a XAML resource file that
is located in the root of the local assembly's project folder:
pack://application:,,,/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that
is located in a subfolder of the local assembly's project folder:
pack://application:,,,/Subfolder/ResourceFile.xaml
Short answer: Use pack URI notation.
Example:
Your URI would look similar to: pack://application:,,,/Resources/my_image.png regardless of where in the XAML you use it.
Documentation:
MSDN - Pack URIs in WPF
In a submodule such as SubModuleA, in the viewmodel of SubModuelA, when you want to access the resource file of SubModuelA instead of the started project.
For example, the resource file's directory is StartApp/SubModuelA/Resource/Data/JsonData.json, In viewmodel of SubModuelA it's path should be
string jsonFile="../../../SubModuleA/Resource/Data/JsonData.json"
I validated this and wrote data into the jsonFile.

Change picture box picture

I added picture box to my form and import 2 pictures, from properties under image property i choose the first picture when the application starting and inside my start button event i want to change my picture to the other picture.
this is what i have try:
pbIndicator.Image = Image.FromFile(#"..\Resources\indicator_green.png");
but file not found exception error occurs.
You should be able to do something like this:
pbIndicator.Image = Resources.indicator_green;
Be sure that in the property window if the Build Action is on Content, and Copy to Output Directory is on Copy if newer.
If you want it to be content. Else use the answer Shadow Wizard gave.
As I wrote in the comment if indicator_green.jpg is an image included as resource via resource file (Resources.resx) then it won't be copied to output directory (it means it's in your project folder because it's used to build executable but it'll be embedded inside your assembly, not deployed standalone).
Resource files will (by default) place resources you add inside Resources folder (and then linked). You can always access them using generated code file for resources:
pbIndicator.Image = Properties.Resources.indicator_green;
You may change namespace Properties and property name according to what you have in your project (by default property name has the same name of the resource and then same name as original file).
Of course you're not forced to embed your resources in your assembly. If you want to deploy them as standalone files just right click Resources folder and add an existing file. In the properties window for that file select Copy always for Copy to output directory and et voila, you'll be able to read it with:
pbIndicator.Image = Image.FromFile(#"Resources\indicator_green.png");
Please note that Resources folder won't be a sub-directory of your output directory (do not forget that source files are not part of installation).
Anyway I suggest you do not build path like that, little bit better would be to do not rely on current folder:
pbIndicator.Image = Image.FromFile(
Path.Combine(Application.StartupFolder, #"Resources\indicator_green.png");
You're not limited to Resources folder, you can do that with any folder (and with any name).

Adding image from resources - Visual Studio 11 Beta C#

I'd like to add an image to my C# WinForm app in Visual Studio 11 Beta. I therefore added my png in the resources tab/images with "add resource" + "from existing file..." (that worked fine and it is listed in the tab).
Now i tried to access it with:
Bitmap Image = new Bitmap(MyProject.Properties.Resources.MyImage); but it doesn't find anything in "Resources". (The only options i get for Resources is: Culture, Equals, ReferenceEquals and ResourceManager)
I also tried to set the build action of the image to embedded resource in the properties tab
Adding the png with its local path works like a charm.
Am I doing it wrong or is there another problem?
(Im working with .NET Framework 4)
If you're trying to load it out of the assembly (build action = embedded resource), you'll need to read the Stream from the assembly like so:
using System.Reflection;
//...
var image = new Bitmap(
Assembly.GetEntryAssembly().
GetManifestResourceStream("MyProject.Properties.Resources.MyImage.png"));
This assumes that your file is located in /Properties/Resources/MyImage.png and that your assembly's root namespace is MyProject.

System.Resources.MissingManifesResourceException - What's causing this?

I just added an image resource to my assembly via the Resources tab in the project properties of my project. The resource is a PNG image. Now when I load the assembly, I'm getting the error shown below. This is occurring in VS 2010.
System.Resources.MissingManifestResourceException: Could not find any resources
appropriate for the specified culture or the neutral culture.
Anyone know what is causing this?
Thanks very much.
Did you set the resource to be embedded?
Check the path in the project explorer within VS, suppose you have this path (from the root of the project), root -> resources -> foobar.png, then the full resource path would be [namespace of your project] followed by resources.foobar.png, for example, suppose the namespace is 'foobar' then it would be "foobar.resources.foobar.png"

Loading Content images from Blend from separate project

I have a VS2010 solution with 5 projects. Two of these projects are called:
MyResources
Application
The Application project contains all of the views and viewmodels for the application to run, and the Resources project contains all the images, resource dictionaries, etc for theming and skinning.
The way I have images set up in Resources, I have their build action set to Content, and Copy set to Copy Always. In my Application project, I reference these files using a pack URI. Example:
"pack://siteoforigin:,,,/Themes/DefaultTheme/BackgroundImage.png"
This works fine for me. The themes folder and all its subfolders are properly copied to the proper folder since I'm using siteoforigin://.
However, this breaks Blendability. When I load the project in Blend 4, I get errors.
If I use siteoforigin, Blend tries to load the images from the executing folder of blend.exe (In this case, C:\Program Files\Microsoft Expression\Blend 4 Beta\Themes\Default_Theme\BackgroundImage.png")
If I change the pack URI to the following:
pack://application:,,,/IQ.IQKiosk.Resources;component/Themes/DefaultTheme/BackgroundImage.png
It tries to look for the image in "themes/default_theme/backgroundimage.png"
If I try:
/MyResources;component/Themes/DefaultTheme/BackgroundImage.png
It tries to look for the image in "C:\MyResources;component\Themes\DefaultTheme\BackgroundImage.png"
If I try:
/Themes/DefaultTheme/BackgroundImage.png
It tries to look for the image in "C:\Themes\DefaultTheme\BackgroundImage.png".
So now I'm stuck. I'm not sure how to reference my images without having to embed them into the resource project, and I can't hard code the directory because my other coworkers have the project in different folders as well.
I tried to think of a way to get the proper URI to the proper locations of the files (relative to the .sln file would be awesome) or have the files get copied over to where blend compiles and executes the project. Alas, I am unable to figure out how.
Does anyone know the proper way to get these images to load?
I figured it out. Instead of using a pack URI, I just used
new Uri(Environment.CurrentDirectory + "\\Themes\\DefaultTheme\\BackgroundImage.png")
and it found the proper folder, since Evironment.CurrentDirectory gave me the proper bin folder where my themes were copied to.
Huzzah!

Categories