Search code examples
c#wpfcsprojmultitargetingmulti-targeting

How to Multi target a library project with WPF controls


I have a class library project that needs to target .NET 3.5 and .NET 4.0, and the way it is done now is the typical way of creating separate projects per target framework and linking files in each project to the same source.

I would like to take advantage of the new csproj format that has come out with .NET Core projects because multitargeting is much simpler with the new csproj format.

I created a new Class Library (.NET Core) project and started to try porting my existing library over.

I don't really need to target .netcoreapp2.0, so my target frameworks look like this

<PropertyGroup>
  <TargetFrameworks>net35;net40</TargetFrameworks>
</PropertyGroup>

and I have the following block of code to help with the .NET 3.5 oddities with the new csproj format.

<PropertyGroup>
  <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
</PropertyGroup>

So far so good. Where things started going downhill is the fact that my class library has WPF Controls. I was getting compile errors because it couldn't find System.Windows and other WPF related items.

I found I could add references to other windows assemblies, so I added the following

<ItemGroup>
  <Reference Include="PresentationFramework" />
  <Reference Include="PresentationCore" />
  <Reference Include="WindowsBase" />
</ItemGroup>

This got rid of most of my errors, but now I am getting errors like The name 'InitializeComponent' does not exist in the current context


Solution

  • Some WPF items migrated to a new library System.Xaml starting at .NET 4.0

    The error The name 'InitializeComponent' does not exist in the current context is being thrown only when the .NET 4.0 target is being built.

    To fix this, the following block needs to be added to the csproj file

    <ItemGroup Condition="'$(TargetFramework)'=='net40'">
      <Reference Include="System.Xaml" />
    </ItemGroup>
    

    Also, the xaml pages need to be built as a page, so the following also needs to be added to the csproj file

    All xaml files that need to be compiled as page.

    <ItemGroup>
      ...
      <Page Include="Path\to\SomeWindow.xaml" />
      <Page Include="Path\to\SomeOtherWindow.xaml" />
      ...
    </ItemGroup>
    

    This will remove the xaml files from your solution explorer, so a workaround was found here that adds the following blocks to get xaml pages built but still showing up in the Solution Explorer.

    <ItemGroup>
      <Page Update="@(Page)" SubType="Designer" Generator="MSBuild:Compile" />
    </ItemGroup>
    
    <ItemGroup>
      <None Include="@(Page)" />
    </ItemGroup>