我的URI必须如此长而明确吗?

Ala*_*lan 2 wpf prism unity-container mvvm

我正在使用Microsoft Prism和Unity 编写模块化应用程序.我的应用程序的Shell项目加载各种DLL,这些DLL都包含自己的/ resources或/ images文件夹和用户界面视图.因此,每个模块都是DLL.

当我尝试在我的应用程序中使用资源时,似乎我必须非常清楚它的位置以使其工作.例如,要在同一模块/ dll中定位图像:

<Image Source="pack://application:,,,/MyCompany.MyProduct.MyModule;Component/Images/ZoomIn.gif" />
Run Code Online (Sandbox Code Playgroud)

我是否真的每次都必须使用URI的长格式版本?我尝试过更短的版本,例如:

pack://application:,,,/Images/ZoomIn.gif

Images/ZoomIn.gif

ZoomIn.gif
Run Code Online (Sandbox Code Playgroud)

等等

我想也许第二个版本应该有效.当我看到Uri的例子时,他们经常说"相对于当前的集会".这是正在运行的可执行程序的程序集吗?或者这是代码所属的程序集(我的库/模块)?

更新:

在Peter Hansen的帮助下,我能够将其缩短为:

<Image Source="../Images/ZoomOut.png" />
Run Code Online (Sandbox Code Playgroud)

显然我不得不使用../因为我的视图是在子文件夹中.我也可以放弃pack://语法,因为类型转换器为我做了这个.

Pet*_*sen 6

在WPF中检索二进制资源时有几个不同的选项,它们都取决于您想要的行为类型.

  1. 如果你的资源应该被嵌入的组件内部,将它们添加到Visual Studio中的项目,并设置生成操作资源.这样它们就会被装入组件中,因此无法轻易更换.

  2. 如果他们应保持宽松的文件,将它们添加到项目中,并设置生成操作内容.还要确保将它们复制到输出目录.这是一个好主意,如果你需要经常更换它们,并且不想每次重新编译程序集.

  3. 如果您希望它们作为松散文件,但由于某些原因(或许它们在编译时不可知)而不希望将它们包含在Visual Studio解决方案中,则可以使用完整路径或使用名为SiteOfOrigin表示法的内容访问它们.我不会这样做,因为这与你的情况无关.

要从代码中访问资源,请使用Pack URI,它可以具有不同的形式:

  • pack://application:,,,/img.jpg
    引用项目根目录中的图像.

  • pack://application:,,,/Folder1/Folder2/img.jpg
    引用项目子文件夹中的图像.

  • pack://application:,,,/NameOfDll;Component/img.jpg
    引用Visual Studio中有引用的不同程序集中的图像.

幸运的是,当从XAML引用资源时,不需要编写完整的URI.
基本上pack://application:,,,可以避免该部分,因为存在TypeConverter,可以将部分位置转换为完整的URI.

对于上面的第1点和第2点,相同的XAML用于引用资源,无论它们是否在执行时作为松散文件存在于程序集旁边或嵌入其中.

但是,在引用过程代码中的资源时,必须使用完全定义的显式URI.

我已经编写了一些代码并包含了一些图像,以展示它是如何工作的.

图像显示运行程序 解决方案探险家视图的图像

相关的XAML:

<StackPanel>
    <TextBlock Text="Embedded in same assembly" />
    <Image Source="gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Embedded in same assembly in a subfolder" />
    <Image Source="Content/Images/gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Embedded in same assembly in a subfolder using full pack URI format" />
    <Image Source="pack://application:,,,/Content/Images/gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Embedded in different assembly" />
    <Image Source="/Module1;Component/gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Embedded in different assembly in a subfolder" />
    <Image Source="/Module1;Component/Images/gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Embedded in different assembly in a subfolder using full Pack URI format" />
    <Image Source="pack://application:,,,/Module1;Component/Images/gift.png" />
</StackPanel>

<StackPanel>
    <TextBlock Text="Setting imagesource from code-behind" />
    <Image x:Name="image1" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

相关代码隐藏:

public Window1()
{
    InitializeComponent();

    //Here we have to use the full Pack URI
    //image1.Source = new BitmapImage(new Uri("/Module1;Component/Images/gift.png")); //Throws exception..
    image1.Source = new BitmapImage(new Uri("pack://application:,,,/Module1;Component/Images/gift.png"));
}
Run Code Online (Sandbox Code Playgroud)

更新
当资源位于使用它的同一程序集中时,应该没有理由包含/NameOfDll;Component/URI 的一部分.我不确定为什么它不适合你的情况.

我已经向Module1添加了一个Window,它只引用了自己程序集中的单个图像,这似乎工作正常.在WPF应用程序中单击按钮时会显示窗口.

<Window x:Class="Module1.WindowTest"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Title="Window from Module1">
    <Grid>
        <Image Source="Images/gift.png" />
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

显示与资源显示的不同的窗口