在 WPF 中检索二进制资源时有几个不同的选项,它们都取决于您想要哪种行为。
如果您的资源应该嵌入到程序集中,请将它们添加到 Visual Studio 中的项目中,并将Build Action设置为Resource。这样它们将被烘焙到组件中,因此不能轻易更改。
如果它们应该保留为松散文件,请将它们添加到项目中,并将Build Action设置为Content。还要确保它们被复制到输出目录。这是一个好主意,如果您需要经常更换它们,并且不想每次都重新编译程序集。
如果您希望它们作为松散文件,但由于某种原因不想将它们包含在您的 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:,,,
可以避免该部分,因为存在可以为您将部分位置转换为完整 URI 的 TypeConverter。
对于上面的第 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>
相关代码隐藏:
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"));
}
更新
当资源在使用它的同一个程序集中时,应该没有理由包含/NameOfDll;Component/
URI 的一部分。我不确定为什么它不适用于您的情况。
我在 Module1 中添加了一个窗口,它只在自己的程序集中引用了一个图像,这似乎工作正常。在 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>