2

In my latest WinForms Project, the code behind for my Main form has started to become too large and difficult to read. In other posts that I have read through, I have seen suggestions that say to create another class that is a partial class of your main form, however, what really bugs me is that the new class that you create automatically generates another blank design window. I'm really looking for a way to split my code behind into multiple partial classes but with only the one main design window.

For example in the project below, my main Window is Form1.cs.

When I first create the new class file (Form1Part2.cs), the file shows up as a c# class that does not contain its own form designer window. (Which is pretty much what I want except it needs to be connected to the Form1 Class, so I can access its controls and properties)

Before making class a partial class:

However, when I make the new class a partial class of Form1, the file becomes a form containing a design window of its own.

After making class a partial class:

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
cj32
  • 23
  • 6

2 Answers2

2

This is why you should avoid partial classes, unless you are writing code generators...

The problem is that you need to make the Form1Part2.cs dependent on Form1.cs, and the only way to do that is to edit the project file:

  <ItemGroup>
    <Compile Include="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Form1.Designer.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>
    <Compile Include="Form1Part2.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
      <SubType>Designer</SubType>
    </EmbeddedResource>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
  </ItemGroup>

The "magic" part is this one:

<Compile Include="Form1Part2.cs">
  <DependentUpon>Form1.cs</DependentUpon>
</Compile>

Because when you add the partial to your code and rename the class it contains, Visual Studio helpfully calls it a form subtype, like this:

<Compile Include="Form1Part2.cs">
    <SubType>Form</SubType>
</Compile>

Which causes the designer to be loaded whenever you click on it, and because it doesn't have a dependency or a .designer.cs file, the Forms Designer doesn't load up the actual form you are designing, just a blank designer (and if you add controls to it, it appears in the partial class and creates an additional RESX file causing all kinds of issues).

Change that XML to make your Form1Part2.cs a dependency of Form1.cs. You can only do this by manually editing the .csproj file. Easiest way is to open it in notepad, but you can edit it in Visual Studio by right clicking on it, unloading the project, then right clicking again and select "Edit xxx.csproj". Make the changes then right click the project and reload it.

After completing this, your new .cs file will appear under the Form1.cs along with the designer and code-behind:

enter image description here

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • I do like the fact that part 2 is now under Form1. However, Now I cannot access any controls I created in the Form1 designer, unless I use the partial keyword and deal with the form subtype. – cj32 Mar 13 '18 at 04:08
  • @cj32 I'm not sure why you can't access them? It works just fine for me. I added a button to the Form1 designer, and in Form1Part2.cs I added a method, and `button1` was there in intellisense. You have to use the `partial` keyword, it is how it knows that it is part of another file. – Ron Beyer Mar 13 '18 at 04:11
  • If you want to access the code by double clicking on the file, that still brings up the designer. The only way around that is to expand the arrow next to `From1Part2.cs` and double click on the `Form1` class. – Ron Beyer Mar 13 '18 at 04:13
0

In my latest WinForms Project, the code behind for my Main form has started to become too large and difficult to read.

This seems concerning to start with.

In other posts that I have read through, I have seen suggestions that say to create another class that is a partial class of your main form

This seems even more concerning, i don't see much of a reason to do this and just seems code-smelly.

Separation of concerns and DRY, create helper classes (or otherwise), that abstract the concerns in the form into manageable logical concerns. You might even find some of it reusable later one while also decluttering the actual true logic from the code behind.

Even if its all just form related i find readable code and classes much easier to digest than 10000 line chucks of code and i'm sure it can be broken apart logically.

Also, maybe some of this would be better off in a MVVM pattern, or even Decoupled in various other ways.

However, its hard to really know without doing an indepth analysis of your code

Update

Sorry i just seen you were in Winforms so the MVVM comment is probably a little irrelevant

TheGeneral
  • 79,002
  • 9
  • 103
  • 141