locked
multiple partial class files cause problems with forms designer RRS feed

  • Question

  • As an experiment I've decided to try splitting Form code (event handlers and the functions they use) across a number of partial classes for my main Form, essentially placing the code supporting a control in its own file. The C# code (.cs) files are created by adding new (empty) code files to the project. I add the namespace and partial class definition the same way the .Designer.cs files do. Everything compiles, runs and functions just fine, as expected. When I use the Forms design UI to add a new Control event handler it places the generated code in the main Form.cs file, as expected. I move the handler to the proper partial file and everything continues to function properly. But the Forms design UI doesn't appear to be able to locate the event handlers in the secondary partial class files. If I use the UI to try to navigate to an existing event handler, e.g. by double-clicking an event in the properties window, it will instead incorrectly navigate to some unrelated location in the main Form.cs file. (Apparently near where it thought it put the code?) Worse still is that when I now create a new event handler using the design UI it will also create an apparently random number of event handler stubs for a subset (not all) of the handlers that reside in the secondary partial classes. These will result in "multiple definition" errors for these handlers when the project is compiled.

    So perhaps I'm missing some way to make these partial class code files subordinate to the main Form.cs file so the designer can find the event handlers? But I've found no UI mechanism to create them that way, nor will the UI allow me to drag these files under the main Form.cs file. But the .Dsigner.cs file is there, so there must be some way to establish this relationship. Though that in and of itself might not solve the problem. Certainly the designer could be corrected to find these handlers, e.g. via reflection, since the compiler has no problem making the connections.

    • Moved by Amanda Zhu Friday, February 15, 2013 6:51 AM
    Wednesday, February 13, 2013 4:26 AM

Answers

  • Thanks Kevin; using the navigation bar is certainly an option. (BTW: I use "old school" Visual C++ 2 keyboard mapping, so CTRL+F2 doesn't do what you think for me. But I figured out what you meant.)

    As a continuation of my experiment I've created a class I call EventProxy that I can use to easily connect all my event handlers with one call in the form constructor (after "InitializeComponent()"). This eliminates the designer confusion for handlers in the other partial classes. Using the same naming conventions the designer uses, e.g. "ControlName_EventName", it finds all the event handler methods in the form class using reflection. I tag the handlers with a custom attribute for identification. The attribute optionally allows specifying the source and event names, so the method can have any desired name. I also allow the handler to omit parameters or declare them with stronger typing, e.g. "object source" can be "ListBox myListBox". This is a nice convenience as giving up the designer aid means typing the handler's signature manually. Since most handlers don't actually care about the parameters you can just type "[EventProxy] void myListBox_Click() { }" and it'll get connected.

    I'm sure there's potential debate as to the value or OO correctness of this kind of code partitioning, but it's an interesting experiment!

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Tuesday, February 19, 2013 7:13 AM
  • Hi Falstaff1978,

    The Windows Forms Designer does not support dividing a designable type's definition into more than two partial implementations. This restriction includes creating a new class file that contains a third partial definition of the type, as well as adding a third partial class definition of the type in either the main file or the designer file. Members defined this way will not be visible in the Windows Forms Designer. See http://msdn.microsoft.com/en-us/library/ms171843.aspx

    This is by design and I don't think you the Windows Forms Designer will work with your secondary partial class.

    Best Regards,


    Bob Wu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Monday, February 18, 2013 9:35 AM
  • For the time beings here is a thought, in the code editor press CTRL+F2, select the object/control interested in (you can press the first letter of the control to get to it) then press TAB, you are now in the events for the selected control. Traverse to the event, if it is in a partial class it will be dim, press ENTER to navigate to it. I agree this is not perfered yet with practice can be faster than using the mouse for the same operation.

    kevininstructor

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Monday, February 18, 2013 2:18 PM

All replies

  • Additional info: I'm using Visual Studio 2012 and working with a solution and project created from scratch in VS 2012.
    Wednesday, February 13, 2013 4:28 AM
  • Hello Falstaff1978,

    Thank you for your post.

    I would like to know what type of application your application is.  Windows Forms app? WPF app?

    Hope you can provide us more information.

    Best regards,


    Amanda Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, February 15, 2013 3:18 AM
  • It is a Windows Forms App.
    Friday, February 15, 2013 3:37 AM
  • And the problem is worse than I reported as there seem to be any number of actions that will cause the development environment to generate the event handler stubs. I just changed the icon for the form and the application (from the default). When I built the solution I got errors for the duplicate stubs that were added by the designer. I'm not sure which action triggered the erroneous edit as I didn't notice it until starting the build.
    Friday, February 15, 2013 3:42 AM
  • Hello,

    I have moved this thread to Windows Forms General forum for better response.

    Best regards,


    Amanda Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, February 15, 2013 6:51 AM
  • Hello,

    I have seen this behavior since partial classes were available at least in VB.NET, had no doubt that it would happen in C#. What I learned was if you (for a simple example) place say a button on a form, double click, copy the event handler code to another file that is a partial of the form, paste the event handler in then go back to the form canvas and double click again the IDE creates the event rather than traversing you to the event just pasted thus causing an IDE error.

    My solution is to be in the form's code editor, select the button (or whatever control I need), scroll thru the events till in this case I locate the Click event which will show as light grey indicating it is in another file, select click and will be traversed to the event.

    Perhaps not the most elegant way but is a work-around.


    kevininstructor

    Friday, February 15, 2013 1:47 PM
  • Hi Falstaff1978,

    The Windows Forms Designer does not support dividing a designable type's definition into more than two partial implementations. This restriction includes creating a new class file that contains a third partial definition of the type, as well as adding a third partial class definition of the type in either the main file or the designer file. Members defined this way will not be visible in the Windows Forms Designer. See http://msdn.microsoft.com/en-us/library/ms171843.aspx

    This is by design and I don't think you the Windows Forms Designer will work with your secondary partial class.

    Best Regards,


    Bob Wu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Monday, February 18, 2013 9:35 AM
  • Thanks for the pointer to the disclaimer about partial classes and the designer. At least I can see it in writing. So "by design", and a feature rather than a bug. Still, allowing this (as a *new* feature enhancement) would make for a very easy and clean way of subdividing form code. Certainly if the compiler and the editor's "Go To Definition" command can find the handlers, the designer should be able to just as easily. :)

    

    Monday, February 18, 2013 10:21 AM
  • For the time beings here is a thought, in the code editor press CTRL+F2, select the object/control interested in (you can press the first letter of the control to get to it) then press TAB, you are now in the events for the selected control. Traverse to the event, if it is in a partial class it will be dim, press ENTER to navigate to it. I agree this is not perfered yet with practice can be faster than using the mouse for the same operation.

    kevininstructor

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Monday, February 18, 2013 2:18 PM
  • Thanks Kevin; using the navigation bar is certainly an option. (BTW: I use "old school" Visual C++ 2 keyboard mapping, so CTRL+F2 doesn't do what you think for me. But I figured out what you meant.)

    As a continuation of my experiment I've created a class I call EventProxy that I can use to easily connect all my event handlers with one call in the form constructor (after "InitializeComponent()"). This eliminates the designer confusion for handlers in the other partial classes. Using the same naming conventions the designer uses, e.g. "ControlName_EventName", it finds all the event handler methods in the form class using reflection. I tag the handlers with a custom attribute for identification. The attribute optionally allows specifying the source and event names, so the method can have any desired name. I also allow the handler to omit parameters or declare them with stronger typing, e.g. "object source" can be "ListBox myListBox". This is a nice convenience as giving up the designer aid means typing the handler's signature manually. Since most handlers don't actually care about the parameters you can just type "[EventProxy] void myListBox_Click() { }" and it'll get connected.

    I'm sure there's potential debate as to the value or OO correctness of this kind of code partitioning, but it's an interesting experiment!

    • Marked as answer by Bob Wu-MT Tuesday, March 12, 2013 5:33 AM
    Tuesday, February 19, 2013 7:13 AM
  • Hi,

    i had same problem and came accross your post, but i wasn't sattisfied. It had to be a solution for this because VS IDE does it.

    Here is the solution :

    Open the .csproj project file with notepad and let's say for a Form1.cs file you will see a configuration like

    <Compile Include="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Form1.Designer.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>

    If you create a new file called Form1Events.cs and put another partial class of Form1 and move the events to the new partial class. In the new .csproj file you the new file like this below

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

    Something is missing you have to tell the VS IDE that this Form1Events.cs file is dependent to Form1.cs. As the IDE do this for Form1.Designer.cs file make the same with Form1Events.cs and put a "DependentUpon" tag into Form1Events.cs. Last the .csproj file look like this below

    <Compile Include="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Form1.Designer.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>
    <Compile Include="Form1Events.cs">
      <DependentUpon>Form1.cs</DependentUpon>
      <SubType>Form</SubType>
    </Compile>

    And if you save the .csproj file the IDE reloads the project and on the Solution exlorer tree you see that the new partial class is put below Form1.cs file. And if you open the designer and double click a previous decalred and moved event it will navigate to the new file.

    Thats all.

    • Proposed as answer by mustiy Friday, October 17, 2014 11:11 AM
    Thursday, October 16, 2014 11:07 PM
  • This works for me! Thanks.
    Thursday, June 4, 2015 9:38 AM
  • Great solution mustiy. Works fine for me (Visual Studio 2013). Thank you!
    Thursday, September 24, 2015 5:44 AM
  • Hi,

    i had same problem and came accross your post, but i wasn't sattisfied. It had to be a solution for this because VS IDE does it.

    Here is the solution :

    Open the .csproj project file with notepad and let's say for a Form1.cs file you will see a configuration like

    <Compile Include="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Form1.Designer.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>

    If you create a new file called Form1Events.cs and put another partial class of Form1 and move the events to the new partial class. In the new .csproj file you the new file like this below

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

    Something is missing you have to tell the VS IDE that this Form1Events.cs file is dependent to Form1.cs. As the IDE do this for Form1.Designer.cs file make the same with Form1Events.cs and put a "DependentUpon" tag into Form1Events.cs. Last the .csproj file look like this below

    <Compile Include="Form1.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Form1.Designer.cs">
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>
    <Compile Include="Form1Events.cs">
      <DependentUpon>Form1.cs</DependentUpon>
      <SubType>Form</SubType>
    </Compile>

    And if you save the .csproj file the IDE reloads the project and on the Solution exlorer tree you see that the new partial class is put below Form1.cs file. And if you open the designer and double click a previous decalred and moved event it will navigate to the new file.

    Thats all.

    Brilliant, quoted for works like a dream.
    Friday, August 19, 2016 6:56 AM