project-system: Add Windows Form does not nest .designer.cs under .cs

I was not able to tell if this issue was already tracked.

Start with this .csproj (15.0.26014.0):

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net452</TargetFramework>
    <RuntimeIdentifier>win</RuntimeIdentifier>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**\*.cs" />
    <EmbeddedResource Include="**\*.resx" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>
</Project>

Select Windows Form in Add New Item and see Form1.cs and Form1.designer.cs nodes are siblings in Solution Explorer, and this is the .csproj:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net452</TargetFramework>
    <RuntimeIdentifier>win</RuntimeIdentifier>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**\*.cs" />
    <EmbeddedResource Include="**\*.resx" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>
  <ItemGroup>
    <Compile Update="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Update="Form1.Designer.cs">
      <SubType>Form</SubType>
    </Compile>
  </ItemGroup>
</Project>

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 28 (5 by maintainers)

Commits related to this issue

Most upvoted comments

This is also bugging me.

I’m trying to move entirely into new csproj land, and while most of my stuff will work as is, I have one(!) WinForms app that is holding me back.

Is there anyway, even if undocumented, to make new csproj deal with WinForms projects (while keeping the designer functional)?

I was able to confirm that a call to LicenseManager.Validate in a custom control constructor causes the NotImplementedException.

That brings this issue to a total of seven issues. Should I start issues for these or are they closely related enough for your purposes?

For me, when I add new form “test.cs” the csproj will contain:

<Compile Update="test.cs">
  <SubType>Form</SubType>
</Compile>

in order to nest the designer, manually edit the csproj by adding right below it, two new nodes in the same ItemGroup:

<Compile Update="test.Designer.cs">
  <SubType>Form</SubType>
  <DependentUpon>test.cs</DependentUpon>
</Compile>
<EmbeddedResource Update="test.resx">
  <DependentUpon>test.cs</DependentUpon>
</EmbeddedResource>

now, Shift+F7 works, designer works. And I did not include MSBuildSdkExtras

I hate to complain because of the amazing results you’ve already had, but six lines feels a bit more verbose than it needs to be. Is something like this possible? (Is SubType needed in the .csproj itself or can that info be cached after examining the contents? Could the nesting be automatic as well?)

    <Compile Update="Form1.cs" SubType="Form" />
    <Compile Update="Form1.designer.cs" SubType="Form" DependentUpon="Form1.cs" />

@jnm2 We’re bringing up WinForms now - let’s use new issues to track each individual issue; bugs we’re aware of are being tracked by the WinForms label: https://github.com/dotnet/project-system/labels/Feature-WinForms.

The nesting itself is being tracked by https://github.com/dotnet/project-system/issues/159, and we’ve implemented for 16.0 using rules of legacy but without DependentUpon. We’ll respect DependentUpon if its present, otherwise, we’ll just auto-nest based on existing rules. I’m going to dupe this bug against it.

@jnm2 @onovotny @johmarjac

I have successfully created the worst msbuild hack of all time…

I basically have two projects for a X winforms project One X.Designer project which I just use for opening up the designer and editing the crap out of my soon to be dead winforms god willing (If MS support this horrid crap in the future)

The Other, X, basically uses msbuild goo to “import” every piece of code/structure from the other project automatically, and that’s the one I actually use to build the final executable with dotnet cli tools

I’m attaching the X.Designer.csproj, X.csproj, here and the Resurrect-WinForms.targets file it imports: X.Designer (the only important thing here is that it builds into the killme folder which we need to know in advance about so we can exclude it inside Resurrect-WinForms.targets) :

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <ProjectGuid>{8F13900E-A99B-4278-9231-5ADB631698FB}</ProjectGuid>
    <ApplicationIcon>X.ico</ApplicationIcon>
    <AssemblyName>X</AssemblyName>
    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x64</Platform>
    <LangVersion>latest</LangVersion>
    <OutputType>WinExe</OutputType>
    <RootNamespace>X</RootNamespace>
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\</SolutionDir>
    <Prefer32Bit>true</Prefer32Bit>
    <DebugType>portable</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <NoWarn>1701</NoWarn>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup Label="MultilingualAppToolkit">
    <MultilingualAppToolkitVersion>4.0</MultilingualAppToolkitVersion>
    <MultilingualFallbackLanguage>en-US</MultilingualFallbackLanguage>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
    <OutputPath>killme\Release\</OutputPath>
    <DefineConstants>TRACE;</DefineConstants>
    <Optimize>true</Optimize>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
    <OutputPath>killme\Debug\</OutputPath>
    <DefineConstants>TRACE;DEBUG;</DefineConstants>
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
   </PropertyGroup>
  <!-- Too much msbuild crap, as created by the old project system -->
</Project>

X.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net471</TargetFramework>
    <ApplicationIcon>..\..\designer\X.Designer\X.ico</ApplicationIcon>
    <OutputType>winexe</OutputType>
    <PlatformTarget>x64</PlatformTarget>
  </PropertyGroup>

  <Import Project="../Resurrect-WinForms.targets" />

  <ItemGroup>
    <PackageReference Include="DockPanelSuite" Version="3.0.3" />
    <PackageReference Include="DockPanelSuite.ThemeVS2015" Version="3.0.3" />
    <PackageReference Include="LibGit2Sharp" Version="0.25.0-preview-0073" />
    <PackageReference Include="NLog" Version="4.5.0-rc04" />
    <PackageReference Include="Npgsql" Version="3.2.6" />
    <PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
  </ItemGroup>

</Project>

And here’s Resurrect-WinForms.targets:

<Project>

  <PropertyGroup>
    <WinFormsPath>..\..\designer\$(AssemblyName).Designer</WinFormsPath>
    <WinFormsExcludes>$(WinFormsPath)\killme\**;$(WinFormsPath)\obj\**</WinFormsExcludes>
  </PropertyGroup>

  <!-- This is a really really special construct we use in our build:
       The idea is that we have X.Designer which is a old-csproj projet we HAVE to continue using
       to preserve the WinForms designer functionality because life sucks https://github.com/dotnet/project-system/issues/1272

       But once the "designing" is done, we don't really have to do anything else with the old format, so we have THIS .csproj
       which does magic and re-includes the files so that we can compile them with "standard" dotnet
  -->
  <ItemGroup>
    <Compile
      Include="$(WinFormsPath)\**\*$(DefaultLanguageSourceExtension)"
      Exclude="$(DefaultItemExcludes);$(WinFormsExcludes)"
      Link="%(RecursiveDir)%(FileName)%(Extension)" />
    <EmbeddedResource
      Include="$(WinFormsPath)\**\*.resx"
      Exclude="$(DefaultItemExcludes);$(WinFormsExcludes)"
      Link="%(RecursiveDir)%(FileName)%(Extension)" />
    <None
      Include="$(WinFormsPath)\**\*"
      Exclude="$(DefaultItemExcludes);$(WinFormsExcludes)"
      Link="%(RecursiveDir)%(FileName)%(Extension)" />
    <None Remove="$(WinFormsPath)\**\*$(DefaultLanguageSourceExtension)" />
    <None Remove="$(WinFormsPath)\**\*.resx" />

    <!-- Causes weird VS2017 15.5 b0rk
    <Compile
     Update="$(WinFormsPath)/**/*.Designer$(DefaultLanguageSourceExtension)"
     DependentUpon="$([System.String]::Copy('%(Filename)').Replace('.Designer', ''))$(DefaultLanguageSourceExtension)"
     SubType="Code" /> -->
    <EmbeddedResource
      Update="$(WinFormsPath)\**\*.resx"
      DependentUpon="%(Filename)$(DefaultLanguageSourceExtension)"
      SubType="Designer" />
    <EmbeddedResource
      Update="$(WinFormsPath)\**\*.zh-CN.resx"
      DependentUpon="$([System.String]::Copy('%(Filename)').Replace('.zh-CN', ''))$(DefaultLanguageSourceExtension)"
      SubType="Designer" />


    <EmbeddedResource Remove="$(WinFormsPath)\Properties\Resources.resx" />
    <EmbeddedResource Remove="$(WinFormsPath)\Properties\Resources.zh-CN.resx" />
    <EmbeddedResource Include="$(WinFormsPath)\Properties\Resources.resx">
      <Link>Properties\Resources.resx</Link>
      <SubType>Designer</SubType>
      <Generator>PublicResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <EmbeddedResource Include="$(WinFormsPath)\Properties\Resources.zh-CN.resx">
      <Link>Properties\Resources.zh-CN.resx</Link>
    </EmbeddedResource>

    <Compile Remove="$(WinFormsPath)\Properties\Resources.Designer.cs" />
    <Compile Include="$(WinFormsPath)\Properties\Resources.Designer.cs">
      <Link>Properties\Resources.Designer.cs</Link>
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
  </ItemGroup>
</Project>

I take no responsibility for anything with this horrid hack I’ve copy pasted above. May the good lord have mercy on your soul.

@onovotny For me it does not even nest Form1.cs and Form1.Designer.cs together allthough I installed (and restored) the MSBuild.Sdk.Extras Package. Here my .csproj


  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net461</TargetFrameworks>
  </PropertyGroup>

<ItemGroup>
    <PackageReference Include="MSBuild.Sdk.Extras" Version="1.2.1" />
  </ItemGroup>

  <ItemGroup>
    <Reference Condition="'$(TargetFramework)' == 'net461'" Include="System.Windows.Forms" />
  </ItemGroup>

  <ItemGroup>
	<Compile Update="Form1.cs">
	  <SubType>Form</SubType>
	</Compile>
	<Compile Update="Form1.Designer.cs">
	  <DesignTime>True</DesignTime>
	  <AutoGen>True</AutoGen>
	  <DependentUpon>Form1.resx</DependentUpon>
	</Compile>
	<Compile Update="Form1.Designer.Designer.cs">
	  <DesignTime>True</DesignTime>
	  <AutoGen>True</AutoGen>
	  <DependentUpon>Form1.Designer.resx</DependentUpon>
	</Compile>
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Update="Form1.Designer.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Form1.Designer.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <EmbeddedResource Update="Form1.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Form1.Designer.cs</LastGenOutput>
    </EmbeddedResource>
  </ItemGroup>
  
</Project>

And that’s how it looks in Solution Explorer image