Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.Net Core 3.0 WPF Resource doesn't work in project #2258

Closed
getandplay opened this issue Nov 28, 2019 · 13 comments
Closed

.Net Core 3.0 WPF Resource doesn't work in project #2258

getandplay opened this issue Nov 28, 2019 · 13 comments
Labels
Bug Product bug (most likely)

Comments

@getandplay
Copy link

getandplay commented Nov 28, 2019

  • .NET Core Version: (e.g. 3.0 Preview1, or daily build number, use dotnet --info)

    .Net Core 3.0 netcoreapp3.0

  • Windows version: (winver)

    win10

  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes/No

    The bug can reproduce in WPF .Net Core but it works fine in .NET Framework 4.7

  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? If yes, please file the issue via the instructions here.

No, I think it is .Net Core Bug

Problem description:

In my solution there are three projects all base on .Net Core 3.0.
- WpfApp1(exe project)
- WpfLibrary1
- Wpf.app.test
And I add an image as Resource in Wps.app.test (I have set the image's build action to Resource), then in WpfLibrary1 I add a ResourceDictionary ,

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <BitmapImage x:Key="Hello" UriSource="pack://application:,,,/Wpf.app.test;component/calendar.png"/>
    
</ResourceDictionary>

In WpfApp1 I use this BitmapImage in my xaml

 <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/WpfLibrary1;component/Test/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <!--It works Fine-->
        <!--It will throw Exception, but .Net FrameWork works fine-->
        <Image Width="200" Height="200" Source="{StaticResource Hello}" HorizontalAlignment="Right"/>
    </Grid>

when I run WpfApp1 I got an error:
image
And we decompile the Wpf.app.test.dll found that there is no Image in the Dll. ( I have set image's build action to Resource )
The Wpf.app.test.project code

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <None Remove="calendar.png" />
  </ItemGroup>

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

</Project>

The Decompile result:
image

Actual behavior:

Throw an exception: System.Windows.Markup.XamlParseException: ''Initialization of 'System.Windows.Media.Imaging.BitmapImage' threw an exception.' Line number '4' and line position '32'.'
Inner Exception
IOException: Cannot locate resource 'calendar.png'.

Expected behaviour:

No Error, No exception

Minimal repro:
Here is the demo for this bug
WpfApp1.zip

@weltkante
Copy link

weltkante commented Nov 28, 2019

You need to add <UseWPF>true</UseWPF> in the PropertyGroup to make it a WPF project and support <Resource> tags.

@vatsan-madhavan
Copy link
Member

vatsan-madhavan commented Nov 28, 2019

<Project Sdk="Microsoft.NET.Sdk"

In addition to UseWPF, you have to use an altogether different SDK - Microsoft.NET.Sdk.WindowsDesktop.

You are not building a WPF or WinForms application yet - what you are building is just a .NET Core library with a name like WpfApp.

Microsoft.NET.Sdk.WindowsDesktop is where WPF and WinForms functionality lives. In order to get WPF specific functionality from this SDK, one must set <UseWpf>true</UseWpf> as @weltkante has rightly observed.

You can type dotnet new wpf to create a new WPF project in the commandline to see what a basic WPF project should look like.

@vatsan-madhavan vatsan-madhavan added this to the Future milestone Nov 28, 2019
@vatsan-madhavan vatsan-madhavan added Question General question, not a problem in source code or documentation (yet) 📭 waiting-author-feedback To request more information from author. labels Nov 28, 2019
@vatsan-madhavan
Copy link
Member

vatsan-madhavan commented Nov 28, 2019

We have tried to help users who get into these sorts of situations by showing warnings.
If someone were to try setting <UseWpf>true</UseWpf> or <UseWindowsForms>true</UseWindowsForms> in a Microsoft.NET.Sdk project today, it will offer a friendly warning and suggest that the developer ought to switch over to the WindowsDesktop SDK (so my additional comment at #2258 (comment) was nice to add, but the SDK would have offered the same hint anyway).

I wonder if it might be worthwhile to look for common WPF items like Page, ApplicationDefinition , SplashScreen and Resource in a Microsoft.NET.Sdk project, and add warnings similar to what we added in https://github.com/dotnet/sdk/pull/3315/files#diff-9c308b83aa992e66e6b5a0e0d935d471. @nguerrera , @dsplaisted, @rladuca thoughts?

@walterlv
Copy link
Contributor

walterlv commented Nov 29, 2019

@weltkante @vatsan-madhavan After adding the <UseWpf>True</UseWpf> into the test project, the error disappears. But how can we explain that there is no exception running in net48?


We can add both net48 and netcoreapp3.0 into all the project csproj files and then we can choose which TargetFramework to run. But if we run in net48, no Exception occurs but in netcoreapp3.0, there will be an IOException. Only compiling in netcoreapp3.0 the Resource is not build into the assembly.

image

image

@vatsan-madhavan
Copy link
Member

vatsan-madhavan commented Nov 29, 2019

The attached repro "works" when building for net48 (or any .NET Framework target) due to a bug - it's not supposed to work (I'll explain the bug in detail further down).

In fact, having a .NET Framework TargetFramework is not sufficient, MSBuildRuntimeType==Full must also be satisfied (which occurs when the project is built using Visual Studio or MSBuild).

If we attempt to build the project using dotnet (where MSBuildRuntimeType==core), you will not encounter the bug that is observable when TargetFramework==net48 (which, ironically, implies that the project will "work"; OTOH when the bug is not present, the project will fail with an exception)

The "bug" is this: In SDK style projects, we didn't intend for WPF specific functionality to be present unless Microsoft.NET.Sdk.WindowsDesktop SDK is used. Contrary to this intention, when MSBuild/Visual Studio is used for builds, .NET Framework's copy of WinFX.targets gets imported by default irrespective of the SDK being used. This happens even for Microsoft.NET.Sdk projects.

image

In the attached project, Wpf.app.test.csproj is a Microsoft.NET.Sdk project with a Resource item that includes calendar.png. Normally, we'd expect this item to be ignored (since Microsoft.NET.Sdk doesnn't include Microsoft.WinFX.targets where targets related to Resource processing normally reside). Due to this bug, .NET Frameworks's copy of WinFX.targets comes into play, and FileClassification and MainResourcesGeneration targets come into play - which embeds the image into the DLL (wpf.app.test.dll).

This bug doesn't present itself when building .NET Core TargetFrameworks, and so when building netcoreapp3.0 the corresponding wpf.app.test.dll doesn't have an embedded calendar.png in it (thus an exception is encountered eventually).

@vatsan-madhavan
Copy link
Member

@nguerrera, @dsplaisted can we do something to prevent inclusion of .NET Framework's WinFX.targets from sdk.targets? For e.g., set some property in sdk.targets, and conditionally leave out importing of $(MSBuildFrameworkToolsPath)\Microsoft.WinFx.targets in $(MSBuildToolsPath)\Microsoft.WinFX.targets ?

@vatsan-madhavan vatsan-madhavan added Bug Product bug (most likely) and removed Question General question, not a problem in source code or documentation (yet) 📭 waiting-author-feedback To request more information from author. labels Nov 29, 2019
@vatsan-madhavan vatsan-madhavan modified the milestones: Future, 5.0 Nov 29, 2019
@getandplay
Copy link
Author

getandplay commented Nov 29, 2019

I have just reset the project with and Microsoft.NET.Sdk.WindowsDesktop ,it works fine. So, is there a way to share the resource between WPF .Net Core and Asp .Net Core?

@vatsan-madhavan
Copy link
Member

So, is there a way to share the resource between WPF .Net Core and Asp .Net Core?

Can you elaborate a bit?

@getandplay
Copy link
Author

Oh, sure. Like I have two projects, one is WPF .Net Core and the other is WindowsForm .Net Core ( or ASP .Net Core ). An image is needed by both projects. So I want to add a project which is based on .Net Core to manage this image. But how I can make this works for both projects?

@vatsan-madhavan
Copy link
Member

<Resource> is a WPF speciifc concept - it compiles the image into the DLL in a very specific way that's unique to how WPF accesses resources. See https://docs.microsoft.com/en-us/dotnet/framework/wpf/app-development/wpf-application-resource-content-and-data-files for a detailed discussion. In general, you can access these resources using Uri's. Also see https://wpf.2000things.com/2014/07/03/1107-accessing-an-embedded-resource-using-a-uri/.

If you want to use image resources a bit more generally, you might want to investigate EmbeddedResource (https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items?view=vs-2019).

@Janek91
Copy link

Janek91 commented Sep 25, 2020

So, to fix it you just need to change

<Project Sdk="Microsoft.NET.Sdk">

to

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

in your project file

@lkrle
Copy link

lkrle commented Jul 17, 2021

I added <UseWPF>true</UseWPF> and Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> but the image can still not be found...

@dsplaisted
Copy link
Member

@leolkr It looks like the original issue was fixed, so if you are running into something similar, it would be best if you could create a new issue with the details of what is happening for you. If you can share a binlog of your project, that is likely to be helpful.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Product bug (most likely)
Projects
None yet
Development

No branches or pull requests

7 participants