且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在 WPF 应用程序中使用来自 .NET Standard 程序集的内容文件

更新时间:2022-11-28 11:59:56

如果您引用复制到输出目录的内容文件,您可以使用路径而不是包 URI.试试这个:

image.Source = new BitmapImage(new Uri($@"{System.AppContext.BaseDirectory}ResourcesImage.png",UriKind.Absolute));

如果您出于某种原因仍需要使用包 URI,请将 pack://application:,,, 替换为 pack://siteoforigin:,,,在路径中,它应该可以工作.

I want to embed a file in a .NET Standard assembly and use it in XAML in a WPF app.

If you set the build action to Resource it is very easy to use the embedded file in other assemblies, but you have to use <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> and <UseWPF>true</UseWPF> to be able to use the Resource build action like so:

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <Resource Include="ResourcesImage.png" />
  </ItemGroup>

Then you can use this Uri from another assembly:

pack://application:,,,/ReferencedAssembly;component/Resources/Image.png

as seen here:

https://docs.microsoft.com/en-us/dotnet/framework/wpf/app-development/pack-uris-in-wpf#resource-file-pack-uris

My question:

If you want only <Project Sdk="Microsoft.NET.Sdk"> and don't want <UseWPF>true</UseWPF> then you have to use the Content build action, because it does not require WPF, as seen here:

https://docs.microsoft.com/en-us/visualstudio/ide/build-actions

And use it like so:

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="ResourcesImage.png">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

Then you should be able to use this Uri from another assembly:

pack://application:,,,/Resources/Image.png

as seen here:

https://docs.microsoft.com/en-us/dotnet/framework/wpf/app-development/pack-uris-in-wpf#content-file-pack-uris

But I get the following exception:

Exception thrown: 'System.Resources.MissingManifestResourceException' in System.Private.CoreLib.dll
Exception thrown: 'System.IO.IOException' in PresentationFramework.dll
Exception thrown: 'System.IO.IOException' in PresentationCore.dll
System.Windows.Data Error: 6 : 'TargetDefaultValueConverter' converter failed to convert value 'pack://application:,,,/Resources/Image.png' (type 'String'); fallback value will be used, if available. BindingExpression:Path=BackgroundImage; DataItem='NavigationNode' (HashCode=663215); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') IOException:'System.IO.IOException: Cannot locate resource 'resources/image.png'.

I have cleaned and rebuilt the whole solution.

What am I doing wrong?

Important: I need to use a pack URI in xaml - too many to convert all existing code from xaml to cs!

If you reference a content file that gets copied to the output directory, you could use a path rather than a pack URI. Try this:

image.Source = new BitmapImage(new Uri($@"{System.AppContext.BaseDirectory}ResourcesImage.png",
    UriKind.Absolute));

If you still need to use a pack URI for some reason, replace pack://application:,,, with pack://siteoforigin:,,, in the path and it should work.