27

I'm migrating my projects to the new visual studio 2017 format which is working nicely for all standard libraries only now I run into problems with my UI libraries where I use Wpf / Xaml.

I cannot figure out howto do this for my user controls. The old item doesn't seem to be valid anymore.

Anybody has an idea howto do this or if it's even possible.

Niek Jannink
  • 1,056
  • 2
  • 12
  • 24

7 Answers7

47

December 13th 2018 - .NET Core 3 Preview 1 was announced

.NET Core 3 will support WPF and WinForms applications. You may try it with Preview version of SDK:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
</Project>

Previous answer

You can use template below to replace old .csproj with. It resolves couple of issues other people templates had.

  1. You don't have to include intermediary *.g.cs files like some suggested to do.
  2. No Main not found error will occur.
  3. No Unable to run your project. The "RunCommand" property is not defined. error will occur.
  4. Includes already configured default Settings and Resources.

Template:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <LanguageTargets>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
    <TargetFramework>net47</TargetFramework>
    <OutputType>WinExe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

  <ItemGroup>
    <!-- App.xaml -->
    <ApplicationDefinition Include="App.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </ApplicationDefinition>

    <!-- XAML elements -->
    <Page Include="**\*.xaml" Exclude="App.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </Page>
    <Compile Update="**\*.xaml.cs" SubType="Code" DependentUpon="%(Filename)" />

    <!-- Resources -->
    <EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
    <Compile Update="Properties\Resources.Designer.cs" AutoGen="True" DependentUpon="Resources.resx" DesignTime="True" />

    <!-- Settings -->
    <None Update="Properties\Settings.settings" Generator="SettingsSingleFileGenerator" LastGenOutput="Settings.Designer.cs" />
    <Compile Update="Properties\Settings.Designer.cs" AutoGen="True" DependentUpon="Settings.settings" />

  </ItemGroup>

  <ItemGroup>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="System.Xaml" />
    <Reference Include="WindowsBase" />
  </ItemGroup>
</Project>
stil
  • 5,306
  • 3
  • 38
  • 44
  • 4
    Your answer was very useful for me. In my case I had the situation with a WPF library. So I had to remove the and not set the OutputType to Exe. – Roman Mueller Jun 19 '17 at 12:06
  • 3
    You should use `MSBuild:Compile` instead of `MSBuild:UpdateDesignTimeXaml` – walterlv May 02 '18 at 11:43
  • 1
    When this project structure, when I edit `Settings.settings`, the VS designer does not regenerate `Settings.Designer.cs`. Likewise, Run Custom Tool has no effect. – Edward Brey Jun 18 '18 at 14:04
  • For some reason, when I build my project, generated files are not updated, and I have to rebuild manually every time I change any of .XAMLs – LOST Jul 15 '18 at 00:48
  • Might also need to add this work-around for the new CPS. https://github.com/dotnet/project-system/issues/2488 – Cameron MacFarland Oct 30 '18 at 06:41
  • For vs2019, you have to remove the languagetargets line. It fails with this line and it is not correctly set directly in the targets file of the sdk. – Yepeekai Aug 07 '19 at 14:50
12

After some searching and trial and error I got it working!

This is the final wpf csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <LanguageTargets>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
    <TargetFrameworks>net451</TargetFrameworks>
    <RootNamespace>MyWpfLibrary</RootNamespace>
    <AssemblyName>MyWpfLibrary</AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Rx-Xaml" Version="2.2.5" />
    <PackageReference Include="reactiveui-core" Version="7.2.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="MyOtherLibrary.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="ReachFramework" />
    <Reference Include="System.Net" />
    <Reference Include="System.Printing" />
    <Reference Include="System.Xaml" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
    <Compile Update="Properties\Resources.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Resources.resx"/>

    <Page Include="**\*.xaml" SubType="Designer" Generator="MSBuild:Compile" />
    <Compile Update="**\*.xaml.cs" SubType="Designer" DependentUpon="%(Filename)" />

    <Resource Include="Fonts\*.otf" />    
    <Resource Include="Images\*.png" />
  </ItemGroup>

  <Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
</Project>
Niek Jannink
  • 1,056
  • 2
  • 12
  • 24
  • 1
    did you attempt to migrate a WPF executable project? If so, how did you do that? I'm getting a "Main not found" error on compile. – Mark Olbert May 23 '17 at 16:49
  • @MarkOlbert You need to set the [build action of App.xaml](https://stackoverflow.com/questions/44140673/wpf-app-using-new-csproj-format/44140869#44140869). I've actually got a list of all the things I had to do to make this work on [my question here](https://stackoverflow.com/questions/44154271/wpf-controls-not-recognized-in-code-behind-when-using-new-csproj-format). – RB. May 24 '17 at 10:14
  • Any idea how to do the same for Telerik reports? I'm not sure what to use as generator. – Sunil Buddala May 08 '18 at 09:25
4

The above solution works for Wpf dll's, but I reverted it because Resharper and the Visual Studio designer where not functional anymore after this change. Mainly because they couldn't pair the xaml and the code-behind at design time. But the project compiles and works.

For a wpf executable you need to do the following:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <LanguageTargets>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
    <TargetFramework>net451</TargetFramework>
    <OutputType>WinExe</OutputType>
    <RootNamespace>MyNamespace</RootNamespace>
    <AssemblyName>MyExe</AssemblyName>
    <ApplicationIcon>MyExe.ico</ApplicationIcon>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <StartupObject>MyNamespace.App</StartupObject>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="System.Xaml" />
    <Reference Include="WindowsBase" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
    <Compile Update="Properties\Resources.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Resources.resx" />

    <None Update="Properties\Settings.settings" Generator="SettingsSingleFileGenerator" LastGenOutput="Settings.Designer.cs" />
    <Compile Update="Properties\Settings.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Settings.settings" />

    <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile" />
    <Compile Update="MainWindow.xaml.cs" DependentUpon="MainWindow.xaml" />
    <Resource Include="Images\*.png" />

    <ApplicationDefinition Include="App.xaml" SubType="Designer" Generator="XamlIntelliSenseFileGenerator" />
    <Compile Update="App.xaml.cs" DependentUpon="App.xaml" />
  </ItemGroup>

  <Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
</Project>
Niek Jannink
  • 1,056
  • 2
  • 12
  • 24
  • Thanx, Niek. BTW, what do the references to LanguageTargets and MSBuildSDKExtrasTargets mean? – Mark Olbert May 25 '17 at 18:55
  • I think the LanguageTargets mean it's C# and not VB.Net or F# and the and I guess the MSBuildSDKExtrasTargets are something for MSBuild. I haven't tried removing them to see what happens :) – Niek Jannink May 31 '17 at 14:46
3

There's Sunburst.NET.Sdk.WPF that allows to use it as .NET SDK. Here's complete example for WPF application where any .cs and .xaml files will be included automatically:

<Project Sdk="Sunburst.NET.Sdk.WPF/1.0.47">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net40</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="../WpfMath/WpfMath.csproj" />
  </ItemGroup>
</Project>

When you build this project with msbuild (notably I had no luck with dotnet build though), it will automatically download SDK from NuGet and set everything up.

ForNeVeR
  • 6,726
  • 5
  • 24
  • 43
  • 1
    This is indeed a much nicer solution for now. Lets wait untill MS releases the full support for Wpf and Winforms. – Niek Jannink Jun 12 '18 at 01:18
  • @FizxMike I was using MSBuild 15. – ForNeVeR Oct 18 '18 at 17:25
  • The Page on github says `Sdk="Sunburst.NET.Sdk.WPF"` but this only gives errors to me. Thanx for hint with the full version qualification `Sdk="Sunburst.NET.Sdk.WPF/1.0.47"`. (The github page has no issues enabled :( ) – springy76 Nov 02 '18 at 15:17
  • @springy76 See [my answer](https://stackoverflow.com/a/59377484/111794) for a possible solution without the Sunburst SDK. – Zev Spitz Dec 17 '19 at 15:35
1

The above solutions may not work with Xamarin.Platforms.WPF on VS2019

Here's a project(based on previous answers) designed for the .net framework (not the .net core app), but can handle .net standard dependencies:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <RootNamespace>TestWPF</RootNamespace>
    <AssemblyName>TestWPF</AssemblyName>
    <TargetFramework>net461</TargetFramework>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>        
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <DebugType>full</DebugType>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
    <DebugType>pdbonly</DebugType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.Platforms" Version="3.0.0" />
    <PackageReference Include="Xamarin.Forms" Version="4.2.0.848062" />
    <PackageReference Include="Xamarin.Forms.Platform.WPF" Version="4.2.0.848062" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="WindowsBase" />
    <Reference Include="System.Xaml" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Update="Properties\Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
    <Compile Update="Properties\Resources.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Resources.resx" />
    <None Update="Properties\Settings.settings" Generator="SettingsSingleFileGenerator" LastGenOutput="Settings.Designer.cs"/>
    <Compile Update="Properties\Settings.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Settings.settings" />

    <ApplicationDefinition Include="App.xaml" Generator="MSBuild:Compile" />
    <Page Include="**\*.xaml" Exclude="App.xaml" SubType="Designer" Generator="MSBuild:Compile" />
    <Compile Update="**\*.xaml.cs" SubType="Designer" DependentUpon="%(Filename)" />

    <EmbeddedResource Remove="**\*.xaml" />

  </ItemGroup>  
  <Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
</Project>
1

Now that .NET Core 3 has been released, you should use it if you can.

But if not, I've found that I can create a separate Shared project for only the XAML items, and I can reference that project from the SDK-style project. Everything builds properly.

Note that the XAML designer doesn't work -- no Intellisense or red squigglies. Visual Studio opens the XAML files with the XML editor.

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
0

Use the official update utility to convert the project:

dotnet tool install --global Project2015To2017.Migrate2019.Tool
dotnet migrate-2019 wizard MyTestProject.csproj

Works for both project and solution files. More information here

Honza Vojtěch
  • 685
  • 1
  • 7
  • 27