views:

335

answers:

10

At the moment my Form1 code is extremely heavy, mainly full of menu and control events. One thing I would like to do is organize it in some way, so I could expand or collapse "related code" (in Visual Studio).

My first attempt at this was to put code relating to the main menu, for example, inside a nested class called "MainMenu", which was within the Form1 class, so that I could simply collapse the nested class when I don't need it. This resulted in all sorts of problems (i.e. I couldn't find a way to set up the main menu inside this nested class).

Is there a simpler solution to this that I'm missing? Or can someone shed some light on why my nested class idea is faulty?

+11  A: 

You can use #region and #endregion to organize code within a class. These regions are then collapseable.

testalino
why the downvote here? - #regions are exactly intended for the problem expressed.
annakata
I always want to run away when I see code cluttered with regions. This is really a bad habit. Instead one should write code that doesn't required regions. I have rarly come across code where this wouldn't be possible and that would improve greatly upon such refactoring.
bitbonk
Yes, thank you very much testalino, the simple solution I was indeed seeking!
Zach Whitfield
yes, this is a bad habit, but it does address what the question actually is, so I don't see that this deserved a downvote
David
Yep, a bad habit indeed, but no need to downvote as it answers the question.
Ruel
Thanks for your input, bitbonk. Is there perhaps a way I could avoid the current situation of having so many events in one class? For a detailed MainMenu system, for example, is there any choice but to have >50 "private static void" events that each lead to a separate method somewhere? Regards
Zach Whitfield
@bitbonk - everything you say is true up to a point (regions used sparingly improve readability and discoverability imho) and this probably isn't the best answer, but it is a valid one, and the best isn't always possible right?
annakata
Regions are like Christmas presents - never know what's inside. Only surprise rarely is enjoyable.
Arnis L.
Just to echo others thoughts: Some places I've worked really frowned on the use of #regions as they hide code and can be used as a proxy for better code organisation. In practice, they can be helpful, but I would personally agree with others advice: Use *sparingly*. Well organised code will *tend* to group itself into discrete, collapsible regions in any case, or even into separate files.
xan
@Zach Whitfield if you like the suggestion you may want to set question to being answered. Of course using regions does not solve any design problems you may have but I would say that 1000 lines of code in the main form is not unusual and grouping those into regions is a good solution.
testalino
A: 

Nested classes are generally frowned upon as being only a slight upgrade from god-classes for one thing, and encapsulation and code reuse being pretty murky.

You should be aiming to express the objects you actually have as individual business classes within your code: one class, one file. Is there any particular reason you aren't doing this?

annakata
I should stipulate that I'm very new to C#. I'm capable of writing basic programs that seem to do the job (most likely not in the optimal way), but still very much learning things like encapsulation.
Zach Whitfield
A: 

Depending on the type of code it is doing will depend on where you can move it.

If its processing data code then you can move this out into separate classes in a different namespace returning the processed data to controls to allow for data binding etc.

If Form1 is getting very heavy with code then is this because you've got too much going on in Form1? Could you break it out into a different/new form?

WestDiscGolf
+13  A: 

While @testalino's answer certainly does what you ask for, I would say that your real problem is probably related to code design. Chances are that the form class simply contains more code than it should, and that some of it ought to move into other classes.

If done in a good way, this might give you some benefits:

  • You will likely get more encapsulated (and less coupled) behavior, when various functions operates on data passed to the methods through parameters and return values instead of fetching and setting values directly in UI controls.
  • You might get a more testable code base (you do have unit tests, right?).
  • It will be easier for several persons to collaborate on the code, since the code is spread across several different code files. This reduces merging conflicts (you do have a source control system, right?). This point may not be as applicable if you are working on something alone, but it doesn't hurt to have this habit anyway.
Fredrik Mörk
I am pretty sure that regions are what the OP was looking for, but this answer was just too good not to vote up anywho +1
Adkins
+1  A: 

If your form has become so big and complex that you suddenly desire to organize it in some way it is a strong hint towards the need of refactoring, which will improve readability, testability and maintainablity of your code. How you actually refactor depends upon your actual code.

Is it a form that has a lot of controls? Think about splitting it up in separate UserControls where each of them displays a certain aspect of your domain data. Do you have a lot of interaction logic, reacting to a lot of events? Maybe introduce a some sort of Controller or EventAggregator.

There are a lot of well known patterns that can help you organize your UI and domain code. This series talks about just that and introduces you to patterns MVC, MVP, EventAggregator and much more. It discusses the patterns in the context of windows forms just as you need it.

bitbonk
Thanks very much for your guidance, I'll give that site a look.
Zach Whitfield
+6  A: 

I suggest you using User Controls to encapsulate some of Form's behavior. This is the simplest solution available for you right now, I guess. You just pick some piece of user interface and extract it to user control and define some public properties accessible from the form.

Keeping all handlers in Form.cs is a bad, bad practice. You must avoid it because it's unmaintanable (I've seen much code like that, and at later stages adding or changing functionality is proven to be impossible without breaking anything, let alone changing the UI without affecting the way app works).

In future, you may want to try different approaches to separation UI from application logic, e.g. explore MVP/MVC patterns.

gaearon
+2  A: 

Use the partial class keyword in order to split your class into several files.

Jérémie Bertrand
A: 

use region! like bellow:

#region parameters
parameter defenitions
#endregion
SaeedAlg
A: 

You could use the summary which is collapsible but I think this is more intended for providing other developers with information, always good practice though!

In VB:

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>

In C#

/// <summary>
///
/// </summary>
/// <remarks></remarks>
gazamatazzer
A: 

I agree with what the other answers say about grouping alike event handlers together in #regions is solid given a massive number of events. In addition, if the code itself in the handlers is voluminous as well, you might want to think of refactoring those into logical business logic classes. Example:

pseudocode before:

private void SomeButton_Click(...)
{
    using (FileStream fs = ...)
    {
        fs.Write(some form data);
        fs.Write(some more form data);
    }

    DoMoreBusinessLogicStuff();
    ...
    // lots more stuff
    ...
}

pseudocode after:

private void SomeButton_Click(...)
{
    IBusinessObject obj = new BusinessObject(injectable form data);

    using (IPersistence store = new FilePersistence(...))
    {
        obj.Persist(store);
    }

    obj.DoBusinessRules();
}

This should move business, persistence and support logic to their own classes and leave your event handlers as lightweight shells designed only to gather UI input and pass it along.

Jesse C. Slicer