Wpf Absolute vs. Relative Pack URIs

24,722

Solution 1

The reason, when running as a separate assembly, that your Relative Pack URI must begin with ../ or no leading backslash is because of how relative URIs are used, from MSDN (emphasis mine):

Absolute vs. Relative Pack URIs

...

If a leading backslash is used, however, the relative pack URI reference is then considered relative to the root of the application.

Therefore if you'd like the images to remain relative to your referenced assembly, simply omit the leading slash or use ../ if in a sub-folder.

See the image below for an example of how this looks at runtime:

Absolute vs. Relative Pack URIs

Solution 2

The answer is this: The leading slash in a relative path always resolves to the main assembly, NOT the assembly that the markup is in.

To make it work the way that MSDN states, I would have to store all icons in an "Icons/" folder in the main assembly, instead of in the custom control dll.

If you choose to store the resources in the dll assembly in an "Icons/" folder, you must reference them with a path relative to the markup you're working on (i.e. "../Icons/folder.png") OR you must qualify the path with the assembly name (i.e. "/AssemblyName;component/Icons/folder.png")

Solution 3

Just replace < ApplicationName> with the name of your application and this should work

Source="/<ApplicationName>;component/Icons/folder.png"
Share:
24,722
Wayne Bloss
Author by

Wayne Bloss

Updated on January 03, 2020

Comments

  • Wayne Bloss
    Wayne Bloss over 4 years

    My question is: Am I reading MSDN wrong OR is MSDN wrong? I am trying to reference an image Resource via relative URI.

    The MSDN page titled Pack URIs in WPF clearly states that:

    "Resource file in subfolder of local assembly" = "/Subfolder/ResourceFile.xaml"

    in Table 2: Relative URIs in Markup (here http://msdn.microsoft.com/en-gb/library/aa970069.aspx ).

    So, I created new WPF/.NET 4.0 projects in Vs2010 (v10.0.40219.1 SP1Rel) to test.

    Startup Project: TryUri
        App.xaml
        MainWindow.xaml
    Custom Ctrl Project: TryUri.CCL
        Icons/folder.png <-- Marked As Resource!
        Views/TestUC.xaml
    

    In TestUC.xaml:

    <Canvas>
        <Border>
            <Image Source="/Icons/folder.png" Height="Auto" Width="Auto" />
        </Border>
    </Canvas>
    

    In MainWindow.xaml:

    // xmlns:uc="clr-namespace:TryUri.CCL.Views;assembly=TryUri.CCL"
    
    <uc:TestUC />
    

    Result: The image does not show up!!

    When I change the path to "../Icons/folder.png" It does work.

    If I copy the Icons/folder.png into the TryUri.CCL/Views/ folder, then "Icons/folder.png" works.

    However, I can never get a leading forward slash to work as in "/Icons/folder.png" the way that MSDN states.

    • Chad La Guardia
      Chad La Guardia over 12 years
      My guess is that your working directory is set wrong in your project. I would check that first.
    • Wayne Bloss
      Wayne Bloss over 12 years
      The working directory would matter if I were trying to access the png as a file. I'm not, it's marked as a Resource. I updated the question to clarify that. Thanks.
    • Wayne Bloss
      Wayne Bloss over 12 years
      I self-answered below. For my project I have chosen to simply use paths relative to the markup (i.e. "../icons/folder.png") as that is the simplest choice IMO.
  • Wayne Bloss
    Wayne Bloss over 12 years
    Thanks. I know that will work, but I want to know why MSDN says that I can just do "/Subfolder/Resource.file-ext".
  • Wayne Bloss
    Wayne Bloss over 12 years
    I tried this and it doesn't work with a leading slash. I have to use "Icons/folder.png" for it to work.
  • Wayne Bloss
    Wayne Bloss over 12 years
    Thanks for the update. Can you comment with a link to your code? I am curious how you got that to work. Also, it looks like you left your TestUC and TestUC2.xaml in the /Views folder of WpfControlLibrary1 contrary to your answer.
  • Sam
    Sam over 12 years
    I'm revising my answer, I believe the .. is required because of how your UserControl is used at run time.