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

4

5

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?

Front answered 4/5, 2017 at 10:59 Comment(6)
Use a "pack" url....and refer to the component that contains the actual resource e.g.: pack://application:,,,/MyAssemblyOrApplicationName;component/Resources/my_image.pngPresentiment
Just in case, do not specify UriKind.Relative on a Pack URI. None of the three answers is actually giving you an appropriate example.Triparted
@Triparted Thank you, it is an important comment. Please look at the edited part of my question to find some additional info.Front
You haven't read the online documentation linked in the answers. pack://application:,,,/../../my_image.png is an invalid Pack URI. Besides that, better do not specify an UriKind at all.Triparted
@MarcinBator Have you figured out in the end how to go "back" in folder structure? I'm having the same issue: https://mcmap.net/q/1923173/-how-to-access-an-image-that-doesn-39-t-belong-to-any-project-assembly-with-relative-path-duplicate/5616592Shelby
@YurenHuang I definitely did figure out how to do it, but unfortunately I have no idea what was the solution (question is 4 years old). There is a good chance that one of the answers for this question helped me solve the issue. Sorry for not beying much of a help and good luck!Front
P
10

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.

enter image description here

Presentiment answered 4/5, 2017 at 11:4 Comment(2)
Thank you for your response, please look at the edited part of my question to find some additional info.Front
I accepted this post as an answer because it provided the most information.Front
C
2

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

Chalcis answered 4/5, 2017 at 11:3 Comment(2)
Thank you for your response, please look at the edited part of my question to find some additional info.Front
It should be new Uri("pack://application:,,,/Resources/my_image.png"); if Image stays in Resources folder of your project.Chalcis
U
1

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

Underclassman answered 4/5, 2017 at 11:1 Comment(1)
Thank you for your response, please look at the edited part of my question to find some additional info.Front
T
0

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.

Treulich answered 26/9, 2019 at 1:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.